Git rebase perd l'historique, alors pourquoi rebase?

j'ai cherché à rebaser avec Git ces derniers jours. La plupart des arguments pour rebaser disent qu'il nettoie l'histoire et la rend plus linéaire. Si vous n'plaine fusionne (par exemple), vous obtenez une histoire qui montre quand l'histoire a divergé et quand il était de retour ensemble. Pour autant que je sache, rebaser supprime toute cette histoire. La Question Est la suivante: Pourquoi ne voudriez-vous pas que l'historique des pensions reflète toutes les façons dont le code s'est développé, y compris où et comment il divergé?

43
demandé sur ngephart 2011-03-09 22:03:17

4 réponses

autant que je sache, rebaser supprime toute cette histoire.

ce n'est pas correct. Le rebasement, comme son nom l'indique, modifie la base de commits. Habituellement, aucun commit n'est perdu dans ce processus (sauf que vous n'avez pas de commit de fusion). Alors que votre argument sur le fait de garder vraiment tout le processus de développement dans l'histoire la façon dont il a été fait est correcte, très souvent cela conduit à des histoires confuses.

surtout lorsque l'on travaille avec d'autres qui travaillent chacun sur leurs propres branches tandis que exigeant certains changements des autres de continuer (par exemple a demande à B de mettre en œuvre quelque chose afin que A puisse utiliser cette caractéristique dans son propre développement), cela conduit à de nombreuses fusions. Par exemple comme ceci:

     #--#--#--#--*-----*-----------------*---#---\         Branch B
    /           /     /                 /         \
---#-----#-----#-----#-----#-----#-----#-----#-----*       Branch A

dans cet exemple nous avons une branche qui fonctionne séparément pour le temps mais tire constamment dans les changements de l'original branche (# sont d'origine s'engage, * sont fusionne).

maintenant si nous faisons un rebase sur la branche B avant de fusionner dans back in, Nous pourrions obtenir ce qui suit:

                             #--#--#--#--#---\         Branch B
                            /                 \
---#---#---#---#---#---#---#---#---------------*       Branch A

cela représente les mêmes changements réels, mais B a été rebasé vers une ancienne commit sur A, de sorte que toutes les fusions sur B qui ont été faites auparavant ne sont plus nécessaires (parce que ces changements sont déjà présents dans cette ancienne commit). Et toutes les propagations qui sont manquantes maintenant, sont les merges, qui ne sont généralement pas contiennent aucune information sur le processus de développement. (Notez que dans cet exemple vous pouvez aussi rebaser ce dernier commit plus tard, pour obtenir une ligne droite, supprimant effectivement toute indication à la deuxième branche)

26
répondu poke 2011-03-09 19:27:46

Imaginez que vous travaillez sur un projet Secret de Domination mondiale. Il y a trois cerveaux sur cette conspiration:

  • Le Génie
  • Le Général
  • Le Pirate Informatique

et ils acceptent tous de venir à leur base secrète dans une semaine chacun avec un plan détaillé.

le hacker informatique, étant un programmeur pragmatique, a suggéré qu'ils utilisent Git pour stocker tous les fichiers des plans. Chacun va bifurquer le repo de projet initial et ils vont fusionner tous en une semaine.

Ils sont tous d'accord et dans les jours suivants, l'histoire va comme ceci:

Le Génie

il a fait un total de 70 commits, 10 chaque jour.

Le Général

Il espionne les pensions de leurs camarades et fait une stratégie pour les battre. Il a fait 3 commits, tout le dernier jour.

Le Pirate Informatique

ce programmeur pragmatique a utilisé des branches. Il a fait 4 plans différents, chacun sur une branche. Chaque branche a été rebasée pour être juste un commit.

sept jours passèrent et le groupe se réunit à nouveau pour fusionner tous les plans en une seule pièce maîtresse. Ils étaient tous impatients de commencer, alors ils ont tous essayé de fusionner toutes les choses par lui-même.

Voici l'histoire:

Le Génie

il a fusionné tous les changements de la déclaration du Général et puis celle du pirate informatique. Et puis, étant une logique amant, il a donné un coup d'oeil au journal. Il s'attendait à voir une évolution logique d'une idée, où les choses ont été construits sur la précédente idées-s'engage.

mais ce que les logs ont montré, était une myriade de commits de différentes idées tout est mélangé dans le temps. Un lecteur ne pouvait pas vraiment comprendre l'évolution, le raisonnement des commits simplement en lisant la ligne de temps des commits.

donc il a fini avec un gâchis, que même un génie ne pouvait pas comprendre.

Le Général

la pensée générale: diviser pour mieux régner!

et donc il a fusionné le repo du Génie sur son repo. Il regarda le journal et vu un tas de s'engage de L'idée de génie, qui a suivi une progression discrète, jusqu'au dernier jour. Le dernier jour, les idées du Général et du génie étaient mélangées.

il espionnait le Hacker de l'ordinateur et savait pour la solution de Rebase. Il a donc repris sa propre idée et réessaie la fusion.

maintenant le journal montre une progression logique Chaque jour.

Le Pirate Informatique

ce programmeur pragmatique a créé une branche d'intégration pour L'idée de génie, une autre pour l'idée générale et une autre pour ses propres idées. Il a rebasé chaque branche. Puis il a tout fusionné en maître.

et tous ses coéquipiers ont vu que sa bûche était bonne. C'était simple. Il a été understable à première vue.

si une idée introduit un problème, il est clair dans laquelle la Commission a été introduite, car il n'y en a qu'une.

ils ont fini par conquérir tout le monde et ils ont disparu l'utilisation de la Subversion.

Et tous étaient heureux.

51
répondu Nerian 2011-08-30 15:03:50

vous faites un rebase principalement pour retravailler votre commits local (celui que vous n'avez pas encore poussé) sur une branche distante (que vous venez de récupérer), afin de résoudre tout conflit localement (c'est-à-dire avant de les repousser vers le repo amont).

Voir " de git et rebase vs fusion questions "et, très détaillé:" git rebase vs git merge " .

mais rebase n'est pas limité à ça scénario, et combiné avec "-- interactive", il permet de ré-commander et de nettoyer votre histoire. Voir aussi " Rogner GIT Archivages/Écraser Historique de GIT ".

pourquoi ne voudriez-vous pas que l'historique des pensions reflète toutes les façons dont le code s'est développé, y compris où et comment il a divergé

  • dans un VCS centralisé, il est important de ne jamais perdre l'histoire, et il devrait en effet, reflètent "toutes les façons dont le code a été élaboré".
  • dans un VCS distribué, où vous pouvez faire toutes sortes d'expériences locales avant édition certaines de vos branches vers l'amont, il est moins logique de garder tout dans l'histoire: pas tout le monde a besoin de cloner et de voir toutes vos branches, tests, alternatives, et ainsi de suite.
11
répondu VonC 2017-05-23 11:33:26

si vous faites une erreur sur un dépôt public et que personne n'y a encore bifurqué/fusionné/retiré, vous pouvez sauver la face et la confusion:

git reset --hard [SHAnumber]

git rebase -f master

git push -f origin HEAD:master

pour vider la poubelle:

git gc
0
répondu mda 2012-01-13 18:29:42