69 votes

Le Parage Des Commits Git/Écraser Historique De Git

J'ai vérifier mon code dans une branche Git toutes les quelques minutes, et les commentaires à la fin des choses comme "Tout cassé un nouveau départ" et autres absurdités.

Ensuite, toutes les quelques minutes/heures/jours, je ne grave s'engager dans un vrai commentaire comme, "correction du bug #22h55, 3ème temps." Comment puis-je séparer ces deux notions? Je voudrais être en mesure de supprimer toutes mes fréquentes-s'engage et il suffit de laisser les plus graves.

105voto

VonC Points 414372

Édité répondre maintenant (dans la seconde moitié de cette entrée) la nouvelle Git1.7 correction! d'action et d' --autosquash option rapide pour engager la réorganisation et de l'édition du message.


Tout d'abord, le classique de l'écrasement de processus, comme l'a fait avant Git1.7.
(Git1.7 a le même processus, ne fait plus rapidement, grâce à la possibilité de validation automatique de réorganisation, par opposition à manuel de réorganisation, et en nettoyant l'écrasement de messages)

Je voudrais être en mesure de supprimer toutes mes fréquentes-archivages et il suffit de laisser les plus graves.

Ceci est appelé l'écraser s'engage.
Vous avez quelques bon exemple de "comit de nettoyage" dans cette Git prêt de l'article:
(Note: le rebase interactif est venu depuis septembre 2007, et permet de les écraser ou de fractionnement ou la suppression ou la réorganisation s'engage: voir aussi la GitPro page)

Un mot de prudence: ne s'engage à ce que n'ont pas été poussé à un référentiel externe. Si d'autres ont fondé travailler les commits que vous allez supprimer, beaucoup de conflits peuvent se produire. Il suffit de ne pas réécrire votre histoire, si elle a été partagée avec d'autres.

alt text

Les 4 derniers s'engage serait plus heureux s'ils étaient enveloppés ensemble

$ git rebase -i HEAD~4

pick 01d1124 Adding license
pick 6340aaa Moving license into its own file
pick ebfd367 Jekyll has become self-aware.
pick 30e0ccb Changed the tagline in the binary, too.

# Rebase 60709da..30e0ccb onto 60709da
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

rebase en utilisant les quatre derniers commits où l' HEAD est avec HEAD~4.
Nous allons juste pour écraser le tout dans un commit.
Donc, en changeant les quatre premières lignes du fichier à cela fera l'affaire:

pick 01d1124 Adding license
squash 6340aaa Moving license into its own file
squash ebfd367 Jekyll has become self-aware.
squash 30e0ccb Changed the tagline in the binary, too.

En gros, cela indique à Git pour combiner tous les quatre s'engage dans la première validation dans la liste. Une fois cette opération effectuée et enregistrée, un autre éditeur apparaît avec le texte suivant:

# This is a combination of 4 commits.
# The first commit's message is:
Adding license

# This is the 2nd commit message:

Moving license into its own file

# This is the 3rd commit message:

Jekyll has become self-aware.

# This is the 4th commit message:

Changed the tagline in the binary, too.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Explicit paths specified without -i nor -o; assuming --only paths...
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   LICENSE
#   modified:   README.textile
#   modified:   Rakefile
#   modified:   bin/jekyll
#

Puisque nous sommes en combinant de manière beaucoup s'engage, Git vous permet de modifier la nouvelle révision du message en se basant sur le reste de la commet impliqués dans le processus. Modifier le message comme bon vous semble, puis sauvegardez et quittez.
Une fois que c'est fait, vos commits ont bien été écrasé!

Created commit 0fc4eea: Creating license file, and making jekyll self-aware.
 4 files changed, 27 insertions(+), 30 deletions(-)
  create mode 100644 LICENSE
    Successfully rebased and updated refs/heads/master.

Et si on regarde l'histoire de nouveau...

alt text


Remarque: pour "commettre l'écrasement" des fins, Git1.7 (février 2010) a introduit 2 nouveaux éléments (comme mentionné par Dustin dans le commentaire):

  • "git rebase -i" appris la nouvelle action "fixup", ce qui écrase le changement, mais n'a pas d'incidence sur les message de journal.
  • "git rebase -i" aussi appris --autosquash option qui est utile avec la nouvelle "correction" de l'action.

Les deux (correction d'action et d' --autosquash option) sont illustrés dans ce Thechnosorcery Réseaux de l'entrée de blog. Ces caractéristiques ont été la cuisine depuis juin dernier 2009 et de débattre de façon plus approfondie , en décembre dernier.

L' fixup action ou une directive pour l'écraser d'un commit, vous auriez manuellement réorganisés dans la commettre modifier la liste d'un rebase --interactive, tout en ignorant le deuxième message de commit, ce qui va rendre le message de l'édition de l'étape plus rapide (il vous suffit de l'enregistrer: l'écrasement du commit aura le premier message de commit seulement)
La résultante de commettre message ne sera le premier commit.

  # s, squash = use commit, but meld into previous commit
  # f, fixup = like "squash", but discard this commit's log message

L' --autosquash option est de faire le commit à la réorganisation des processus automatiquement pour vous:

Si vous savez ce que s'engager que vous voulez de squash quelque chose de que vous pouvez vous engager avec un message de "squash! $other_commit_subject". Alors si vous exécutez @git rebase --interactive --autosquash commitish@, la ligne sera automatiquement définie comme la courge, et placé au-dessous de la validation avec le sujet de $other_commit_subject.

(En fait, l' squash! pouvez utiliser seulement le début d'un autre message de commit)

$ vim Foo.txt
$ git commit -am "Change all the 'Bar's to 'Foo's"
[topic 8374d8e] Change all the 'Bar's to 'Foo's
 1 files changed, 2 insertions(+), 2 deletions(-)
$ vim Bar.txt
$ git commit -am "Change all the 'Foo's to 'Bar's"
[topic 2d12ce8] Change all the 'Foo's to 'Bar's
 1 files changed, 1 insertions(+), 1 deletions(-)

$ vim Foo.txt
$ git commit -am "squash! Change all the 'Bar's"
[topic 259a7e6] squash! Change all the 'Bar's
 1 files changed, 2 insertions(+), 1 deletions(-)

Voir? Voici la troisième commettre utilise seulement le début du premier message de commit.
Un rebase --interactive --autosquash de déplacer la prévenue s'engager au-dessous de la pertinente:

pick 8374d8e Change all the 'Bar's to 'Foo's
squash 259a7e6 squash! Change all the 'Bar's
pick 2d12ce8 Change all the 'Foo's to 'Bar's

Le message de l'édition serait:

# This is a combination of 2 commits.
# The first commit's message is:

Change all the 'Bar's to 'Foo's

# This is the 2nd commit message:

squash! Change all the 'Bar's

Sens par défaut, vous devez garder à l'écrasement de l'opération enregistrée dans le message de commit.
Mais avec la correction! la directive, vous pouvez garder que l'écrasement "invisible" dans le message de commit, tout en continuant à bénéficier de la validation automatique de réorganisation avec l' --autosquash option (et le fait que votre deuxième message de livraison est basé sur le premier commit que vous voulez être écrasé avec).

pick 8374d8e Change all the 'Bar's to 'Foo's
fixup cfc6e54 fixup! Change all the 'Bar's
pick 2d12ce8 Change all the 'Foo's to 'Bar's

Le message par défaut sera:

# This is a combination of 2 commits.
# The first commit's message is:

Change all the 'Bar's to 'Foo's

# The 2nd commit message will be skipped:

#    fixup! Change all the 'Bar's

Notez que l' fixup! commit message est déjà commenté.
Vous pouvez simplement enregistrer le message en tant que-est, et l'original de votre message de commit sera conservé.
Très pratique pour, y compris les modifications lorsque vous vous rendez compte que vous avez oublié d'ajouter une partie d'une ancienne commettre.

Maintenant, si vous voulez de correction ou de squash basée sur la précédente livraison vous venez de le faire, Jacob Helwig (l'auteur de la Technosorcery Réseaux de l'entrée de blog) recommande ce qui suit alias:

[alias]
    fixup = !sh -c 'git commit -m \"fixup! $(git log -1 --format='\\''%s'\\'' $@)\"' -
    squash = !sh -c 'git commit -m \"squash! $(git log -1 --format='\\''%s'\\'' $@)\"' -

Et pour faire un rebase interactif qui vous permettra de toujours bénéficier de la réorganisation automatique de commits destiné à être écrasé:

[alias]
    ri = rebase --interactive --autosquash

27voto

Yar Points 25421

À l'aide de Soft Reset au Lieu de Rebase de Squash Historique de GIT

Je pense que la longueur de VonC réponses parle des volumes-littéralement-sur le degré de complexité git rebase . C'est mon extension d' une autre réponse à une question de la mienne.

  1. Vous avez une succursale ticket-201 que vous ramifié master. Vous voulez faire semblant que tous les commits de ticket-201 n'est jamais arrivé, mais que vous l'avez fait tout le travail d'un seul coup.
  2. Réinitialisation logicielle pour le point de branchement à l'aide de git reset --soft hashhash devrait être un commit de hachage qui est en ticket-201's journal.
  3. Valider vos modifications en utilisant les ajouter ensuite à s'engager. Maintenant, l'histoire de la branche aura seulement le premier commit et le nouveau avec le nouveau stuff.

Faisant Place des Histoires De l'Arbitraire s'Engage dans les Différentes Branches

À l'aide de réinitialisations, vous pouvez réécrire l'histoire comme bon vous semble, si vos modifications vont perdre le charme d'avoir le droit d'horodatage. En supposant que vous n'avez pas de soins à ce sujet (la date/heure sur vos fichiers seront assez, peut-être?), ou si vous voulez jouer avec les commits que vous allez, vous pouvez suivre ces étapes:

  1. Commander une nouvelle branche à l' commit0 (faire semblant que c'est un hash): git checkout -b new-history commit0
  2. Maintenant, vous pouvez obtenir les fichiers d' commit5: git reset --hard commit5
  3. Revenez à votre point d'indice: git reset --soft commit0
  4. S'engager et ce sera la seconde s'engager dans la branche.

Cette idée est simple, efficace et flexible.

9voto

Yar Points 25421

À L'Aide De La Courge À La Place

Récemment, j'ai travaillé dans une autre branche et à l'aide de squash. L'autre branche est appelée temp, puis-je utiliser git merge temp --squash à le ramener dans le réel de la branche qui est poussé vers le serveur.

Flux de travail est quelque chose comme cela, en supposant que je travaille en Ticket65252:

git branch -d temp #remove old temp bbranch
git checkout -b temp
# work work work, committing all the way
git checkout Ticket65252
git merge temp --squash
git commit -m "Some message here"

Avantages sur l'utilisation de rebase? De façon moins compliquée.

Avantages sur l'utilisation de reset --hard puis reset --soft? Moins déroutant et un peu moins enclins à faire des erreurs.

0voto

Jason Punyon Points 21244

L'utilisation de git rebase -i de choisir et de squash vos commits ensemble.

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