web-dev-qa-db-fra.com

Pourquoi le même conflit réapparaît-il lorsque j'utilise git rebase?

J'ai lu des questions pertinentes sur git merge et git rebase sur SO, mais je ne comprends toujours pas ce qui se passe sous le capot.

Voici notre situation de branchement:

MASTER------------------------
        \        \
         \        \----Feature B---
          \                        \
           \-----Feature A----------\---Feature A+B

Nous avons 2 branches de fonction qui proviennent de master à un moment différent, maintenant nous voulons combiner les 2 branches. Nous voulons suivre le first rebase then merge pratique, mais lorsque nous rebasons la fonction A en fonction B, nous obtenons des conflits. C'est prévu, car les deux fonctionnalités (et master) ont des changements dans les mêmes domaines. Mais ce qui est étrange, c'est que le même conflit continue de réapparaître après git rebase --continue. Cela nous rend fous, donc nous finissons par abandonner le rebase et utilisons git merge. Il s'avère que les conflits sont en fait faciles à résoudre.

Ma question est double:

  1. Est git rebase adapté à notre situation? Ou est-ce que le rebase n'est bon que pour introduire quelques (1 ou 2) changements?
  2. Que se passe-t-il sous le capot qui fait réapparaître le même conflit encore et encore? Ma compréhension est rebase résoudre les conflits un à la fois, mais en comparant quel commit à quoi?

Articles de Relavant sur SO:

35
NeoWang

Le rebase est-il adapté à votre situation?

Basé sur le fait que Feature A et Feature B semble être partagé branches, je dirais non .

La refondation est un moyen de fusionner des branches sans avoir des validations de fusion (c'est-à-dire des validations qui ont deux parents ou plus) en le faisant apparaître comme une histoire linéaire. Il est préférable de fusionner branches locales, c'est-à-dire les branches qui n'existent que dans votre référentiel local et qui n'ont pas été publiées à d'autres personnes. Pourquoi? Pour au moins deux raisons:

  1. Le changement de base modifie les ID de validation (c'est-à-dire le SHA-1 hachages de leurs métadonnées). Cela signifie qu'une fois que vous avez poussé les validations rebasées vers la branche partagée, elles apparaîtront comme complètement les nouvelles validations pour quiconque les récupère sur leur référentiel local, même s'ils contiennent toujours les mêmes modifications. Maintenant, si quelqu'un a ajouté de nouveaux commits en plus des anciens entre-temps, il devra les déplacer. Cela crée une confusion inutile.

  2. Lorsque vous fusionnez des branches publiques, vous avez souvent voulez pour avoir ces merge commits afin de pouvoir suivre comment les commits se sont déplacés entre les branches. Cette information est perdue avec le rebasage.

Que se passe-t-il sous le capot?

Juste une fusion régulière. La différence est que git rebase fusionne un commit à la fois en plus du précédent à partir du parent commun. git merge fusionne deux validations - avec l'ensemble de leurs modifications - en une seule opération, vous n'avez donc à résoudre les conflits qu'une seule fois.

Mise à jour: résolution des conflits récurrents

Comme @Jubobs l'a souligné dans les commentaires, Git a une solution automatisée pour résoudre les conflits qui se produisent plusieurs fois: git rerere , ou " réutiliser la résolution enregistrée".

Après avoir activé rerere dans votre fichier de configuration (rerere.enabled true) chaque fois qu'un conflit de fusion se produit, Git enregistrera l'état des fichiers en conflit avant et après vous les fusionnez. La prochaine fois que le même conflit se produira - un conflit impliquant les exactement les mêmes lignes des deux côtés de la fusion - Git appliquera automatiquement la même résolution qu'il avait enregistrée précédemment. Il vous en informera également dans la sortie de fusion:

CONFLIT (contenu): fusionner le conflit dans 'certains fichiers'
Résolution d'un "fichier" en utilisant la résolution précédente.

Ici vous pouvez trouver plus de détails sur la façon de gérer les conflits en utilisant git rerere.

46
Enrico Campidoglio