Rebasage et que veut-on dire par rebasage des commits poussés

109

On dit souvent que vous ne devez pas rebaser les commits que vous avez déjà poussés. Quelle pourrait être la signification de cela?

Hemant Kumar
la source

Réponses:

80

Le livre ProGit a une bonne explication .

La réponse précise à votre question se trouve dans la section intitulée « Les dangers de la réinstallation ». Une citation de cette section:

Lorsque vous rebasez des éléments, vous abandonnez les commits existants et en créez de nouveaux qui sont similaires mais différents. Si vous poussez des commits quelque part et que d'autres les tirent vers le bas et basent leur travail sur eux, puis vous réécrivez ces commits avec git rebase et les poussez à nouveau, vos collaborateurs devront fusionner à nouveau leur travail et les choses deviendront compliquées lorsque vous essayez de ramenez leur travail dans le vôtre.

Mise à jour: d'
après votre commentaire ci-dessous, il semble que vous rencontriez des difficultés avec votre flux de travail Git. Voici quelques références qui peuvent vous aider:

Tim Henigan
la source
Merci pour l'explication. Donc, juste pour rendre ma compréhension plus claire, après avoir poussé certains changements, je ne devrais pas utiliser git rebase(--interactive?) Pour réécrire cet historique, c'est sûr la recette de l'échec. branchez (depuis la branche X) et poussez-la, il est parfaitement normal de rebaser à nouveau après qu'un autre développeur change de branche de rubrique. Essentiellement, j'utilise mergedepuis un certain temps, mais nous sommes dans le même bateau que darwinweb.net/articles/86 et l'historique est presque inutilisable.
Hemant Kumar
@Hemant: Rebasing commits après avoir poussé vers un repo public est généralement une mauvaise idée. Cela étant dit, les conseils de l'article de darwinweb que vous avez cité semblent raisonnables si votre flux de travail ressemble au leur. Voir ma réponse mise à jour pour une liste d'autres références qui pourraient aider.
Tim Henigan
Veuillez mettre à jour un lien vers la page «ProGit» sur «Équipe gérée privée» vers git-scm.com/book/en
...
Donc techniquement, git commits reste le même mais "abandonner les commits existants et en créer de nouveaux qui sont similaires mais différents" est juste le même commit avec un identifiant sha1 différent? eh bien, ce serait la seule façon évidente de comprendre pourquoi les collaborateurs doivent fusionner leur propre travail!
Ciasto piekarz
@Ciastopiekarz, c'est parce que vous réécrivez l'historique dans le dépôt en amont, et les dépôts locaux d'autres développeurs peuvent avoir des pointeurs vers cela. Maintenant, leurs pointeurs sont périmés: le client git n'a pas d'autre alternative que d'utiliser des pointeurs plus anciens et de compter sur l'humain pour trier le reste. Il s'agit d'une re-fusion, et cela peut être TRÈS compliqué avec beaucoup de changements déroutants qui doivent être triés manuellement! Ainsi, la recommandation de ne jamais rebaser tout ce qui a déjà été poussé vers un dépôt en amont. C'est un bon conseil et il ne faut pas l'ignorer à moins que vous ne soyez un expert avec des connaissances approfondies.
Forbin
240

Pour comprendre cela, nous devons comprendre un peu comment fonctionne git. Un référentiel git est une structure arborescente, où les nœuds de l'arborescence sont validés. Voici un exemple de référentiel très simple: Quand tu fourches

il a quatre commits sur la branche principale, et chaque commit a un ID (dans ce cas, a, b, c et d). Vous remarquerez que d est actuellement le dernier commit (ou HEAD) de la branche master. entrez la description de l'image ici

Ici, nous avons deux branches: master et my-branch. Vous pouvez voir que master et my-branch contiennent tous les deux des commits a et b, mais alors ils commencent à diverger: master contient c et d, tandis que my-branch contient e et f. On dit que b est la "base de fusion" de my-branch par rapport à master - ou plus communément, juste la "base". Cela a du sens: vous pouvez voir que my-branch était basé sur une version précédente de master.

Alors disons que my-branch est devenu obsolète, et que vous voulez le mettre à jour avec la dernière version de master. Pour le dire autrement, my-branch doit contenir c et d. Vous pouvez faire une fusion, mais cela fait que la branche contient des commits de fusion étranges qui rendent l'examen de la demande d'extraction beaucoup plus difficile. Au lieu de cela, vous pouvez effectuer un rebase.

entrez la description de l'image ici

Quand vous rebase, git trouve la base de votre branche (dans ce cas, b), trouve tous les commits entre cette base et HEAD (dans ce cas, e et f), et rejoue ces commits sur le HEAD de la branche vous rebasez sur (dans ce cas, maître). Git crée en fait de nouveaux commits qui représentent à quoi ressemblent vos changements par-dessus master: dans le diagramme, ces commits sont appelés e ′ et f ′. Git n'efface pas vos commits précédents: e et f ne sont pas modifiés, et si quelque chose ne va pas avec le rebase, vous pouvez revenir à la façon dont les choses étaient auparavant.

Lorsque de nombreuses personnes différentes travaillent sur un projet de manière simulée, les demandes d'extraction peuvent rapidement devenir obsolètes. Une pull request "obsolète" est une requête qui n'est plus à jour avec la ligne principale de développement et qui doit être mise à jour avant de pouvoir être fusionnée dans le projet. La raison la plus courante pour laquelle les demandes d'extraction deviennent obsolètes est due à des conflits: si deux demandes d'extraction modifient toutes les deux des lignes similaires dans le même fichier et qu'une demande d'extraction est fusionnée, la demande d'extraction non fusionnée aura désormais un conflit. Parfois, une pull request peut devenir obsolète sans conflits: peut-être que les changements dans un fichier différent dans la base de code nécessitent des changements correspondants dans votre pull request pour se conformer à la nouvelle architecture, ou peut-être que la branche a été créée quand quelqu'un a accidentellement fusionné des tests unitaires échouants avec le branche principale. Quelle que soit la raison,

pseudoCoder
la source
68

Rebasing réécrit l'histoire. Si personne ne connaît cette histoire, c'est parfaitement bien. Si, cependant, cette histoire est connue du public, la réécriture de l'histoire dans Git fonctionne exactement comme elle le fait dans le monde réel: vous avez besoin d'une conspiration.

Les complots sont vraiment difficiles à maintenir ensemble, il vaut donc mieux éviter de rebaser les branches publiques en premier lieu.

Notez qu'il existe des exemples de conspirations réussies: la pubranche du dépôt git de Junio ​​C. Hamano (le dépôt officiel du Git SCM) est fréquemment rebasée. La façon dont cela fonctionne est que presque tous ceux qui utilisent pusont également abonnés à la liste de diffusion des développeurs Git, et le fait que la pubranche soit rebasée est largement diffusé sur la liste de diffusion et sur le site Web de Git.

Jörg W Mittag
la source
4
+1. Je pense que la pubranche de git.git est un exemple extrêmement utile de la façon d'utiliser rebase dans un flux de travail (public). Pour ceux qui ne le connaissent pas, l'idée générale est de rebaser les branches de rubrique qui n'ont pas de commits dans next(la branche instable juste avant de fusionner avec master), puis de reconstruire la pubranche en réinitialisant nextet en fusionnant toutes les branches de rubrique. (Source: Documentation / howto / maintenez-git.txt git.kernel.org/?p=git/git.git;a=blob;f=Documentation/howto/… )
Cascabel
25
+1 pour "la réécriture de l'histoire dans Git fonctionne exactement comme dans le monde réel: vous avez besoin d'un complot"
Sleeper Smith
"Une annonce publique n'est pas nécessaire puisque pu est une branche jetable, comme décrit ci-dessus." git-scm.com/docs/gitworkflows Nous faisons quelque chose de similaire au travail, "TEMP-something-latest" est une branche jetable qui est une combinaison des dernières modifications, cela pourrait être une fusion de plusieurs branches de fonctionnalités, peut être supprimée et recréé à tout moment et ne doit pas être développé.
pilkch
6

Un rebase modifie l'historique de votre référentiel. Si vous transférez les commits vers le monde, c'est-à-dire que vous les rendez disponibles à d'autres, et que vous changez ensuite votre vision de l'historique des commits, il devient difficile de travailler avec quelqu'un qui a votre ancienne histoire.

Rebase considéré comme nuisible est un bon aperçu, je pense.

dsolimano
la source