Nous utilisons git et avons une branche principale et des branches de développeur. Je dois ajouter une nouvelle fonctionnalité, puis rebaser les commits vers le maître, puis pousser le maître vers le serveur CI.
Le problème est que si j'ai des conflits pendant le rebase, je ne peux pas pousser vers ma branche de développeur distante (sur Github) une fois le rebase terminé, jusqu'à ce que je tire ma branche distante. Cela provoque des validations en double. Lorsqu'il n'y a pas de conflit, fonctionne comme prévu.
question: après le rebase et la résolution des conflits, comment synchroniser mes branches de développeur locales et distantes sans créer de duplication de commits
Installer:
// 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 '[email protected]: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
ÉDITER
Il semble donc que cela interrompra le flux de travail:
developer1 travaillant sur myNewFeature developer2 travaillant sur hisNewFeature utilisent tous deux master comme branche principale
developer2 fusionne myNewFeature dans hisNewFeature
developer1 rebase, résout les conflits, puis force les poussées vers la branche distante pour myNewFeature
quelques jours plus tard, developer2 fusionne à nouveau myNewFeature dans hisNewFeature
Cela incitera-t-il les autres développeurs à détester le développeur1?
we
? faites-vous partie d'une équipe qui ne se limite pas à vous?they
dites (aux gens qui en savent plus que moi) que si vous partagez votre code, vous ne devriez pas l'utiliserrebase
. Pourquoi tu ne fais pas justegit pull
etgit merge
?force
la poussée)rewriting history
, c'est unrebase
Réponses:
Tout d'abord, vous et ceux avec qui vous travaillez devez convenir si une branche de sujet / développement est destinée au développement partagé ou simplement à la vôtre. Les autres développeurs savent qu'il ne faut pas fusionner sur mes branches de développement car elles seront rebasées à tout moment. Habituellement, le flux de travail est le suivant:
Ensuite, pour rester à jour avec la télécommande, je ferai ce qui suit:
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 changer de branche de développement. Deuxièmement, c'est un mécanisme de sécurité pour m'assurer de ne pas écraser les changements non cachés / validés. De plus, si je ne peux pas effectuer une fusion rapide vers la branche principale, cela signifie que quelqu'un a rebasé le maître distant (pour lequel il doit être sévèrement fouetté) ou que je me suis accidentellement engagé à maîtriser et que je dois nettoyer ma fin.
Ensuite, lorsque la télécommande a changé et que j'ai rapidement avancé vers la dernière, je rebase:
D'autres développeurs savent alors qu'ils devront rebaser leurs branches de développement à partir de ma dernière:
Ce qui se traduit par une histoire beaucoup plus propre:
Ne fusionnez pas les commits dans les deux sens à votre guise. Non seulement cela crée des validations en double et rend l'historique impossible à suivre, mais il devient presque impossible de trouver des régressions à partir d'un changement spécifique (c'est pourquoi 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 cela.
Il semble également que d'autres développeurs effectuent des commits dans vos branches de développement. Pouvez-vous le confirmer?
Le seul moment pour fusionner est lorsque votre branche thématique est prête à être acceptée
master
.Sur une note latérale. Si plusieurs développeurs s'engagent dans le même référentiel, vous devriez tous envisager d'avoir des branches nommées pour distinguer les branches de développement des développeurs. Par exemple:
Ainsi, toutes les branches de sujet des développeurs résident dans leur propre ensemble imbriqué.
la source
--force
drapeau lorsque vous le faitesgit push -f origin devel0
?git push
ne peut pas avancer rapidement (c'est-à-dire que l'historique sha ne correspond pas), vous devez forcer push pour écraser l'historique précédent avec le nouvel historique généré à partir degit rebase
.Vous devez forcer le push car vous avez déplacé les commits plus bas dans la ligne git s'attend à ce que vous ajoutiez des commits à la pointe de la branche.
git push -f origin myNewFeature
résoudra votre problème.Astuce: ci-dessus est un usage légitime de la force de poussée. Ne réécrivez jamais l'histoire sur un référentiel accessible au public ou beaucoup de gens vous détesteront.
la source
git push --force-with-lease
est beaucoup plus sûre que l'utilisationgit push --force
git push --force-with-lease origin HEAD
- en supposant que votre branche cible est déjàLa principale chose à garder à l'esprit ici est ce que font le pull et le rebase dans les coulisses.
Un pull fera essentiellement deux choses: récupérer et fusionner. Lorsque vous incluez --rebase, il effectuera un rebase au lieu de la fusion.
Un rebase est un peu comme cacher toutes vos modifications locales depuis que vous avez créé une branche, faire avancer rapidement votre branche vers le dernier commit sur la cible et désinstaller vos modifications dans l'ordre en haut.
(Cela explique pourquoi vous pouvez recevoir plusieurs invites de résolution de conflit lorsque vous effectuez un rebase par rapport à la résolution de conflit que vous pouvez obtenir avec 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 modifications rebasées vers les branches distantes car il s'agit de réécrire l'historique. Ofcoarse, jamais n'est un peu fort car il y a presque toujours des exceptions. Le cas où vous devez maintenir une version distante de votre référentiel local pour travailler sur un environnement spécifique par exemple.
Cela vous obligera parfois à pousser les modifications rebasées en utilisant la force:
Ou dans certains cas, votre administrateur peut avoir supprimé la possibilité de forcer, vous devez donc supprimer et recréer:
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 succursale distante. Cela peut signifier que vous travaillez ensemble au départ avec des fusions et que vous les rebasez dans un format de validation plus gérable juste avant de maîtriser et de supprimer votre branche active.
N'oubliez pas que vous pouvez presque toujours utiliser le GC de git en profitant de:
C'est une énorme bouée de sauvetage car vous pouvez revenir à un état plus stable si vous vous perdez dans toute votre gestion de rebase / conflit.
la source
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 - vous n'êtes généralement pas censé publier des branches où vous réécrivez l'histoire (ou plutôt ne réécrivez pas l'histoire une fois publiée). Une façon serait d'utiliser un nom de branche comme
wip/myNewFeature
, puis de mentionner que leswip
branches seront rebasées en maître de temps en temps.la source
git push --force-with-lease
est beaucoup plus sûre que l'utilisationgit push --force
-f
pour une poussée forcée normale :)La réponse générale qui a déjà été donnée - à utiliser
git push -f origin myNewFeature
pour pousser des changements rebasés - est un bon point de départ. J'écris cette réponse pour aborder la question de savoir si cela interrompra votre flux de travail.Si nous supposons que vous allez utiliser
git pull --rebase ...
(ou une variante à ce sujet) suivi d'une poussée forcée vers la branche distante, alors la chose qui rompt le flux de travail dans votre exemple est la fusion de developer2myNewFeature
danshisNewFeature
. Il est logique de pouvoir rebaser votre propre branche de fonctionnalité tant que personne d'autre ne travaille sur cette branche, vous avez donc besoin de règles pour délimiter le territoire de la branche.Vous pouvez contourner cela en a) établissant une règle à partir de laquelle vous ne fusionnez que
master
, ou b) en créant unedevelop
branche collective , sur laquelle vous basez votre propremyNewFeature
branche, et en établissant une règle à partir de laquelle vous ne fusionnez quedevelop
.master
sera alors réservé uniquement pour les jalons ou les versions (ou quelle que soit la manière dont vous souhaitez le configurer), etdevelop
sera l'endroit où vous pousserez chaque fonctionnalité lorsqu'elle est prête à être intégrée dans d'autres branches de fonctionnalités.Je pense que cela pourrait être considéré comme une version simplifiée du flux de travail Gitflow.
la source
Je suis d'accord avec MrCholo , et peut-être que Trevor Norris pourrait envisager de mettre à jour sa bonne réponse pour remplacer
avec
la source