150 votes

ne peut pas pousser vers une branche après un rebasement

Nous utilisons git et avons une branche master et des branches développeurs. J'ai besoin d'ajouter une nouvelle fonctionnalité et de rebaser les commits vers master, puis de pousser master vers le serveur CI.

Le problème est que si j'ai des conflits pendant le rebasement, je ne peux pas pousser vers ma branche de développement distante (sur Github) une fois le rebasement terminé, jusqu'à ce que je tire ma branche distante. Cela provoque des commits en double. Lorsqu'il n'y a pas de conflits, cela fonctionne comme prévu.

question : après le rebasement et la résolution des conflits, comment puis-je synchroniser mes branches de développement locales et distantes sans créer des commits en double ?

Mise en place :

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

EDITAR

Il semble donc que cela va briser le flux de travail :

développeur1 travaillant sur myNewFeature le développeur2 travaille sur saNewFeature tous deux utilisent master comme branche principale

le développeur2 fusionne maNewFeature avec saNewFeature

developer1 rebase, résout les conflits, puis force les pousses vers la branche distante pour myNewFeature

quelques jours plus tard, le développeur2, fusionne à nouveau maNewFeature dans saNewFeature

Est-ce que cela va amener les autres développeurs à détester le développeur 1 ?

103voto

Trev Norris Points 2686

Tout d'abord, vous et ceux avec qui vous travaillez devez vous mettre d'accord sur le fait qu'une branche topic/devel est destinée au développement partagé ou seulement au vôtre. Les autres développeurs savent qu'ils ne doivent pas fusionner sur mes branches de développement car elles seront rebasées à tout moment. En général, le flux de travail est le suivant :

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

Ensuite, pour rester à jour avec la télécommande, je vais faire ce qui suit :

 git fetch origin
 git checkout master
 git merge --ff origin/master

Je fais cela pour deux raisons. D'abord parce que cela me permet de voir s'il y a des changements à distance sans avoir besoin de passer de ma branche devel. Deuxièmement, c'est un mécanisme de sécurité pour s'assurer que je n'écrase pas les modifications non stockées/commandées. Enfin, si je ne peux pas fusionner rapidement vers la branche master, cela signifie que soit quelqu'un a modifié la branche master distante (ce pour quoi il doit être sévèrement puni), soit je me suis accidentellement engagé vers master et je dois faire le ménage de mon côté.

Ensuite, quand la télécommande a changé et que j'ai fait une avance rapide sur la dernière version, je rebase :

git checkout devel0
git rebase master
git push -f origin devel0

Les autres développeurs savent alors qu'ils devront rebaser leurs branches devel sur ma dernière version :

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

Ce qui donne un historique beaucoup plus propre :

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

Ne fais pas ça. fusionner les commits d'avant en arrière à votre guise. Non seulement cela crée des commits en double et rend l'historique impossible à suivre, mais trouver des régressions à partir d'un changement spécifique devient presque impossible (ce qui est la raison pour laquelle vous utilisez le contrôle de version en premier lieu, n'est-ce pas ?) Le problème que vous rencontrez est le résultat de cette façon de faire.

Il semble également que d'autres développeurs puissent faire des commits dans vos branches devel. Pouvez-vous le confirmer ?

Le seul moment où il faut fusionner est lorsque la branche du sujet est prête à être acceptée dans le système de gestion de l'information. master .

En passant. Si plusieurs développeurs commettent sur le même dépôt, vous devriez tous envisager d'avoir des branches nommées pour distinguer les branches devel des développeurs. Par exemple :

git branch 'my-name/devel-branch'

Ainsi, toutes les branches thématiques des développeurs résident dans leur propre ensemble imbriqué.

63voto

Learath2 Points 2430

Vous devez forcer le push car vous avez déplacé les commits plus loin sur la ligne ; git s'attend à ce que vous ajoutiez des commits à l'extrémité de la branche. git push -f origin myNewFeature va régler votre problème.

Conseil : Ce qui précède est une utilisation légitime de la force de poussée. Ne réécrivez jamais l'historique d'un dépôt accessible au public ou beaucoup de gens vous détesteront.

33voto

Matthew Sanders Points 924

La principale chose à garder à l'esprit ici est ce que pull et rebase font en coulisse.

Un pull fait essentiellement deux choses : récupérer et fusionner. Si vous incluez --rebase, il fera un rebasement au lieu d'une fusion.

Un rebasement revient à stocker toutes vos modifications locales depuis la création de la branche, à faire avancer votre branche jusqu'au dernier commit sur la cible, et à dépiler vos modifications dans l'ordre par-dessus.

(Cela explique pourquoi vous pouvez recevoir plusieurs messages de résolution de conflit lorsque vous effectuez un rebasement, alors qu'une seule résolution de conflit peut être obtenue lors d'une fusion. Vous avez la possibilité de résoudre un conflit sur CHAQUE commit qui est rebasé afin de préserver autrement vos commits).

Vous ne voulez jamais pousser les changements rebasés vers les branches distantes car cela revient à réécrire l'histoire. Bien sûr, "jamais" est un peu fort car il y a presque toujours des exceptions. Le cas où vous avez besoin de maintenir une version distante de votre dépôt local pour travailler sur un environnement spécifique par exemple.

Cela vous obligera à pousser les changements rebasés à certains moments, soit en utilisant force :

git push -f origin newfeature

Ou, dans certains cas, votre administrateur peut avoir supprimé la possibilité de forcer, de sorte que vous devez supprimer et recréer :

git push origin :newfeature
git push origin newfeature

Dans les deux cas, vous devez être absolument sûr de savoir ce que vous faites si quelqu'un d'autre collabore avec vous sur votre branche distante. Cela peut signifier que vous travaillez ensemble initialement avec des fusions et que vous les refondez dans un format de livraison plus facile à gérer juste avant de passer à master et de supprimer votre branche de travail.

Rappelez-vous que vous pouvez presque toujours vous rabattre sur la GC de git en profitant de :

git reflog

C'est un ÉNORME moyen de sauver des vies, car vous pouvez revenir à un état plus stable si vous vous perdez dans la gestion de vos rebases et conflits.

2voto

Sylvain Lesage Points 410

Je suis d'accord avec MrCholo et peut-être Trevor Norris pourrait envisager de mettre à jour son bonne réponse pour remplacer

git push -f origin devel0

avec

git push --force-with-lease origin devel0

2voto

ThiefMaster Points 135805

Vous devez effectuer une poussée forcée, c'est-à-dire git push -f origin myNewFeature

Oh, et vous feriez mieux de vous assurer que les gens ne basent rien sur votre branche de développement - en général, vous n'êtes pas censé publier des branches où vous réécrivez l'histoire du tout (ou plutôt ne réécrivez pas l'histoire une fois publiée). Une solution serait d'utiliser un nom de branche comme wip/myNewFeature et en mentionnant ensuite que wip Les branches seront rebasées sur master de temps en temps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X