542 votes

Fusionner (avec squash) tous les changements d'une autre branche en un seul commit

Dans Git, existe-t-il un moyen de fusionner toutes les modifications d'une branche dans une autre, mais de les écraser dans un seul commit en même temps ?

Je travaille souvent sur une nouvelle fonctionnalité dans une branche séparée et je fais régulièrement des commits/push - principalement pour la sauvegarde ou pour transférer ce sur quoi je travaille sur une autre machine. La plupart du temps, ces commits disent "Feature xxx WIP" ou quelque chose de redondant.

Une fois que ce travail est terminé et que je veux fusionner la branche WIP dans master, j'aimerais me débarrasser de tous ces commits intermédiaires, et n'avoir qu'un seul commit propre.

Existe-t-il un moyen simple de procéder ?

Sinon, pourquoi pas une commande qui écraserait tous les commits sur une branche depuis le moment où elle a été branchée ?

672voto

fseto Points 2449

Une autre option est git merge --squash <feature branch> et enfin faire un git commit .

En Fusion Git

--squash

--no-squash

Produire l'arbre de travail et [ ] ), mais n'effectuent pas de un commit ou déplacer l'index HEAD , $GIT_DIR/MERGE_HEAD t git commit pour créer une fusion commit. Cela vous permet de créer une unique sur la branche actuelle dont l'effet est le même que la fusion d'une autre branche (ou plus dans dans le cas d'une pieuvre).

1 votes

Fonctionnalité intéressante ! J'adore git. Même si je l'utiliserai certainement à l'avenir, je recommande toujours de se familiariser avec rebase -i. C'est une bonne compétence à avoir, juste au cas où vous voudriez vraiment faire plus qu'un seul commit.

5 votes

Attention : cela fonctionne, mais le message de livraison par défaut inclut le journal de la branche en cours de fusion. Le problème est que cela ressemble au format que vous voyez normalement, où le texte entier affiché ne fait pas partie du message de livraison, mais dans ce cas, il le fait. Donc si vous ne voulez pas de tout cela, vous devez le supprimer manuellement de votre message de validation. J'aurais dû tester cela avant de l'utiliser...

32 votes

Cela, et, soyez averti que la branche ne sera pas considérée comme fusionnée. stackoverflow.com/questions/19308790/

236voto

Brad Robinson Points 5469

Je l'ai trouvé ! La commande Merge a une fonction --squash option

git checkout master
git merge --squash WIP

à ce stade, tout est fusionné, éventuellement conflictuel, mais non validé. Je peux donc maintenant :

git add .
git commit -m "Merged WIP"

3 votes

Que fait le git add . faire ?

1 votes

@MichaelPotter Il ajoute tous les fichiers et les modifications.

2 votes

git add . ajoute tous les fichiers non ignorés dans le répertoire actuel, je me méfierais de la possibilité de récupérer des fichiers non désirés de cette manière.

34voto

fseto Points 2449

Essayer git rebase -i master sur votre branche de fonctionnalités. Vous pouvez alors changer tous les 'pick' sauf un en 'squash' pour combiner les commits. Voir écraser les commits avec rebase

Enfin, vous pouvez effectuer la fusion à partir de la branche master.

12 votes

Oui, cela fonctionne, mais je ne veux pas les inconvénients d'un rebasement interactif. Je veux juste que tout ce qui a été fait depuis la branche soit aplati.

3 votes

+1 Cela permet d'avoir un historique propre. Il est beaucoup plus facile d'identifier et de gérer les commits en tant que correctifs individuels, cartes, histoires, etc.

18voto

rara_tiru Points 333

Utilisation git merge --squash <feature branch> en tant que réponse acceptée suggère de le faire, mais il ne montrera pas la branche fusionnée comme étant réellement fusionnée.

C'est pourquoi une solution encore meilleure consiste à :

  • Créer une nouvelle branche à partir de la dernier maître Le projet doit être validé dans la branche maîtresse où la branche de fonctionnalités a été initiée.
  • Fusionner <feature branch> dans le tableau ci-dessus à l'aide de git merge --squash
  • Fusionner la branche nouvellement créée dans master. De cette manière, la branche de fonctionnalités ne contiendra qu'un seul commit et la fusion sera représentée par une illustration courte et ordonnée.

Ce wiki explique la procédure en détail.

Dans l'exemple suivant, la capture d'écran de gauche est le résultat de l'opération suivante qgit et la capture d'écran de droite est le résultat de :

git log --graph --decorate --pretty=oneline --abbrev-commit

Les deux Les captures d'écran montrent la même gamme de commits dans le même dépôt. Néanmoins, celle de droite est plus compacte grâce à --squash .

  • Au fil du temps, le master s'est écartée de la db .
  • Lorsque le db était prête, une nouvelle branche appelée tag a été créé dans le cadre du même commit de master que db a sa racine.
  • En tag a git merge --squash db a été effectuée, puis toutes les modifications ont été mises en scène et validées en une seule fois.
  • En master , tag ont été fusionnés : git merge tag .
  • La branche search n'est pas pertinent et n'est en aucun cas fusionné.

enter image description here

7voto

Akbar Pulatov Points 1105

2020 mise à jour

Avec la --squash Le drapeau ressemble à deux branches parallèles sans lien entre elles :

enter image description here

Le tri des commits en fonction de la date ressemble à ceci :

enter image description here

Personnellement, je n'aime pas l'option --squash, essayez cette astuce, peut-être qu'elle correspond à vos besoins, je l'utilise pour de petits projets :

  1. git init
  2. git checkout -b dev
  3. Plusieurs commits dans dev
  4. Après avoir fait quelques bons commits dans dev (mais pas encore fusionnés dans master), si vous ne voulez pas que tous les commits soient copiés dans la branche master, alors changez intentionnellement quelque chose dans master et (ajoutez quelques lignes vides dans le fichier README et faites un commit dans master),
  5. git merge dev Il en résulte un conflit de fusion (lignes vides dans le README), résolvez-le, faites un commit avec le nouveau message que vous voulez, et c'est TERMINÉ. Voici la représentation visuelle de ce processus.

null commit pour un conflit de fusion intentionnel, nommez-le comme vous le souhaitez

null commit for intentionally merge conflict

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