Je travaille sur un projet qui a 2 branches, A et B. Je travaille généralement sur la branche A et je fusionne des éléments de la branche B. Pour la fusion, je fais généralement:
git merge origin/branchB
Cependant, je voudrais également conserver une copie locale de la branche B, car je peux parfois consulter la branche sans d'abord fusionner avec ma branche A. Pour cela, je ferais:
git checkout branchB
git pull
git checkout branchA
Existe-t-il un moyen de faire ce qui précède en une seule commande, et sans avoir à changer de branche d'avant en arrière? Dois-je utiliser git update-ref
pour cela? Comment?
git
git-merge
git-pull
git-checkout
Charles
la source
la source
--no-ff
option, ce qui entraîne tout de même l'enregistrement d'une validation de fusion. Si cela vous intéresse, ma réponse montre comment vous pouvez y parvenir - pas aussi robuste que ma réponse affichée ici, mais les forces des deux pourraient certainement être combinées.Réponses:
La réponse courte
Tant que vous effectuez une fusion à avance rapide , vous pouvez simplement utiliser
Exemples:
Bien que la réponse d'Amber fonctionne également dans les cas d'avance rapide, l'utilisation
git fetch
de cette manière est un peu plus sûre que le simple déplacement forcé de la référence de branche, cargit fetch
cela empêchera automatiquement les avances non rapides accidentelles tant que vous ne les utilisez pas+
dans le refspec.La réponse longue
Vous ne pouvez pas fusionner une branche B dans la branche A sans vérifier d'abord A si cela entraînerait une fusion sans avance rapide. En effet, une copie de travail est nécessaire pour résoudre tout conflit potentiel.
Cependant, dans le cas des fusions à avance rapide, cela est possible , car de telles fusions ne peuvent jamais entraîner de conflits, par définition. Pour ce faire sans vérifier d'abord une branche, vous pouvez utiliser
git fetch
avec une refspec.Voici un exemple de mise à jour
master
(interdiction des modifications non rapides) si vous avezfeature
extrait une autre branche :Ce cas d'utilisation est si courant que vous voudrez probablement en faire un alias dans votre fichier de configuration git, comme celui-ci:
Ce que cet alias fait est le suivant:
git checkout HEAD
: ceci met votre copie de travail dans un état de tête détachée. Ceci est utile si vous souhaitez mettre à jourmaster
pendant que vous l'avez récupéré. Je pense que c'était nécessaire parce que sinon la référence de branche pourmaster
ne bougera pas, mais je ne me souviens pas si c'est vraiment tout de suite.git fetch upstream master:master
: cela fait avancer rapidement votre section localemaster
au même endroit queupstream/master
.git checkout -
vérifie votre branche précédemment extraite (c'est ce que-
fait dans ce cas).La syntaxe de
git fetch
for (non-) fast-forward mergesSi vous voulez que la
fetch
commande échoue si la mise à jour n'est pas en avance rapide, alors vous utilisez simplement une spécification du formulaireSi vous souhaitez autoriser les mises à jour sans avance rapide, vous ajoutez alors un
+
au début de la spécification de référence:Notez que vous pouvez passer votre dépôt local en tant que paramètre "distant" en utilisant
.
:La documentation
De la
git fetch
documentation qui explique cette syntaxe (soulignement le mien):Voir également
Git checkout et fusionner sans toucher à l'arbre de travail
Fusion sans changer le répertoire de travail
la source
git checkout --quiet HEAD
est àgit checkout --quiet --detach
partir de Git 1.7.5.git fetch . origin/foo:foo
mettre à jour mon foo local vers mon origine locale / foogit checkout -
astuce! Aussi simple quecd -
.Non, il n'y en a pas. Une extraction de la branche cible est nécessaire pour vous permettre de résoudre les conflits, entre autres (si Git n'est pas en mesure de les fusionner automatiquement).
Cependant, si la fusion est rapide, vous n'avez pas besoin de vérifier la branche cible, car vous n'avez en fait pas besoin de fusionner - tout ce que vous avez à faire est de mettre à jour la branche pour pointer vers le nouvelle tête ref. Vous pouvez le faire avec
git branch -f
:Mettra à jour
branch-b
pour pointer vers le chef debranch-a
.L'
-f
option signifie--force
, ce qui signifie que vous devez être prudent lorsque vous l'utilisez.la source
git reset
ne fonctionne que sur la branche actuellement extraite.git fetch upstream branch-b:branch-b
(tiré de cette réponse ).git fetch <remote> B:A
, où B et A sont des branches complètement différentes, mais B peut être fusionné rapidement en A. Vous pouvez également passer votre référentiel local en tant que "distant" en utilisant.
comme alias distant:git fetch . B:A
.branch -f
pourrait être dangereux, comme vous le soulignez. Alors ne l'utilisez pas! Utilisezfetch origin branchB:branchB
, qui échouera en toute sécurité si la fusion n'est pas rapide.Comme l'a dit Amber, les fusions rapides sont le seul cas dans lequel vous pourriez imaginer faire cela. Toute autre fusion doit théoriquement passer par la fusion à trois, appliquer des correctifs, résoudre les conflits - et cela signifie qu'il doit y avoir des fichiers.
Il se trouve que j'ai un script que j'utilise exactement pour cela: faire des fusions d'avance rapide sans toucher à l'arbre de travail (sauf si vous fusionnez dans HEAD). Il est un peu long, car il est au moins un peu robuste - il vérifie que la fusion serait une avance rapide, puis l'exécute sans vérifier la branche, mais produisant les mêmes résultats que si vous l'aviez - vous voyez le
diff --stat
résumé des modifications, et l'entrée dans le reflog est exactement comme une fusion d'avance rapide, au lieu de la «réinitialisation» que vous obtenez si vous utilisezbranch -f
. Si vous nommezgit-merge-ff
et déposez - le dans votre répertoire bin, vous pouvez l' appeler comme une commande git:git merge-ff
.PS Si quelqu'un voit des problèmes avec ce script, veuillez commenter! C'était un travail d'écriture et d'oubli, mais je serais heureux de l'améliorer.
la source
# or git branch -f localbranch remote/remotebranch
pour me rappeler la source et les options. A donné à votre commentaire sur l'autre lien un +1."$branch@{u}"
comme le commit à fusionner pour obtenir la branche en amont (à partir de kernel.org/pub/software/scm/git/docs/gitrevisions.html )Vous ne pouvez le faire que si la fusion est une avance rapide. Si ce n'est pas le cas, alors git doit faire extraire les fichiers pour pouvoir les fusionner!
Pour le faire pour une avance rapide uniquement :
où
<commit>
est le commit récupéré, celui vers lequel vous souhaitez effectuer une avance rapide. C'est essentiellement comme utilisergit branch -f
pour déplacer la branche, sauf qu'elle l'enregistre également dans le reflog comme si vous aviez réellement fait la fusion.S'il vous plaît, s'il vous plaît, s'il vous plaît ne faites pas cela pour quelque chose qui n'est pas une avance rapide, ou vous allez simplement réinitialiser votre branche à l'autre commit. (Pour vérifier, voyez si
git merge-base <branch> <commit>
donne le SHA1 de la branche.)la source
git merge-base --is-ancestor <A> <B>
. "B" étant la chose qui doit être fusionnée en "A". Par exemple, A = master et B = develop, en veillant à ce que develop soit rapidement transmissible en master. Remarque: il existe avec 0 s'il n'est pas compatible, existe avec 1 s'il l'est.Dans votre cas, vous pouvez utiliser
qui fait ce que vous voulez (en supposant que la fusion soit rapide). Si la branche ne peut pas être mise à jour car elle nécessite une fusion sans avance rapide, cela échoue en toute sécurité avec un message.
Cette forme de récupération propose également des options plus utiles:
Notez qu'il
<remote>
peut s'agir d'un référentiel local et<sourceBranch>
peut être une branche de suivi. Vous pouvez donc mettre à jour une branche locale, même si elle n'est pas extraite, sans accéder au réseau .Actuellement, mon accès au serveur en amont se fait via un VPN lent, donc je me connecte périodiquement,
git fetch
pour mettre à jour toutes les télécommandes, puis me déconnecter. Si, par exemple, le maître distant a changé, je peux le fairepour mettre à jour mon maître local en toute sécurité, même si j'ai actuellement une autre succursale vérifiée. Aucun accès réseau requis.
la source
Une autre façon, certes assez brute, est de simplement recréer la branche:
Cela supprime la branche locale obsolète et en recrée une avec le même nom, alors utilisez-la avec précaution ...
la source
Vous pouvez cloner le référentiel et faire la fusion dans le nouveau référentiel. Sur le même système de fichiers, cela liera en dur plutôt que de copier la plupart des données. Terminez en tirant les résultats dans le référentiel d'origine.
la source
Entrez git-forward-merge :
https://github.com/schuyler1d/git-forward-merge
Fonctionne uniquement pour les fusions automatiques, s'il y a des conflits, vous devez utiliser la fusion régulière.
la source
Dans de nombreux cas (comme la fusion), vous pouvez simplement utiliser la branche distante sans avoir à mettre à jour la branche de suivi locale. L'ajout d'un message dans le reflog sonne comme une surpuissance et l'empêchera d'être plus rapide. Pour faciliter la récupération, ajoutez ce qui suit dans votre configuration git
Tapez ensuite
pour voir l'historique récent de votre succursale
la source
[core]
pas être[user]
? (et il est par défautJ'ai écrit une fonction shell pour un cas d'utilisation similaire que je rencontre quotidiennement sur des projets. Il s'agit essentiellement d'un raccourci pour garder les succursales locales à jour avec une branche commune comme développer avant d'ouvrir un PR, etc.
glmh
("git pull and merge here") sera automatiquementcheckout branchB
,pull
le plus récent, recheckout branchA
etmerge branchB
.Ne répond pas à la nécessité de conserver une copie locale de branchA, mais pourrait facilement être modifié pour ce faire en ajoutant une étape avant d'extraire branchB. Quelque chose comme...
Pour les fusions rapides simples, ceci passe à l'invite de message de validation.
Pour les fusions non rapides, cela place votre branche dans l'état de résolution de conflit (vous devrez probablement intervenir).
Pour configurer, ajouter à
.bashrc
ou.zshrc
, etc.:Usage:
la source
Une autre façon de le faire efficacement est:
Comme il s'agit d'un minuscule
-d
, il ne le supprimera que si les données existent toujours quelque part. C'est similaire à la réponse de @ kkoehne, sauf qu'elle ne force pas. À cause de-t
cela, il réinstalle la télécommande.J'avais un besoin légèrement différent de celui d'OP, qui était de créer une nouvelle branche de fonctionnalité
develop
(oumaster
), après avoir fusionné une demande d'extraction. Cela peut être accompli dans une ligne sans force, mais cela ne met pas à jour ladevelop
branche locale . Il s'agit simplement de vérifier une nouvelle branche et de la baser surorigin/develop
:la source
juste pour tirer le maître sans vérifier le maître que j'utilise
git fetch origin master:master
la source
Il est absolument possible de faire n'importe quelle fusion, même les fusions non rapides, sans
git checkout
. Laworktree
réponse de @grego est un bon indice. Pour développer cela:Vous avez maintenant fusionné la branche de travail locale avec la
master
branche locale sans changer de caisse.la source
Si vous souhaitez conserver le même arbre que l'une des branches que vous souhaitez fusionner (c'est-à-dire pas une véritable "fusion"), vous pouvez le faire comme ceci.
la source
Vous pouvez essayer
git worktree
d'avoir deux branches ouvertes côte à côte, cela semble être ce que vous voulez, mais très différent de certaines des autres réponses que j'ai vues ici.De cette façon, vous pouvez avoir deux branches distinctes dans le même référentiel git, vous n'avez donc qu'à récupérer une fois pour obtenir des mises à jour dans les deux arborescences de travail (plutôt que d'avoir à git cloner deux fois et git tirer sur chacune)
Worktree créera un nouveau répertoire de travail pour votre code où vous pouvez faire extraire une branche différente simultanément au lieu de permuter les branches en place.
Lorsque vous souhaitez l'enlever, vous pouvez nettoyer avec
la source