Comment puis-je fusionner deux commits en un si j'ai déjà commencé rebase?

j'essaie de fusionner 2 commits en 1, donc j'ai suivi " squashing commits with rebase "de git ready .

j'ai couru

git rebase --interactive HEAD~2

dans l'éditeur résultant, je change pick en squash et puis save-quit, mais le rebase échoue avec l'erreur

Ne peut pas "squash" sans précédent commit

maintenant que mon arbre de travail a j'ai atteint cet état, j'ai du mal à me remettre. La commande git rebase --interactive HEAD~2 échoue avec

rebase Interactive déjà commencé

et git rebase --continue échoue avec

Ne peut pas "squash" sans précédent commit

1017
demandé sur JGallardo 2010-04-02 00:56:53

11 réponses

résumé

le message d'erreur

Ne peut pas "squash" sans précédent commit

signifie que vous avez probablement tenté de " vous écraser vers le bas." Git toujours courges, plus récente, s'engager dans une ancienne commettre ou "vers le haut" comme on en trouve sur le rebase interactif todo liste, qui est dans un commit sur une ligne précédente. Changer la commande sur la première ligne de votre liste de choses à faire squash produira toujours cette erreur car il n'y a rien pour la première propagation.

The Fix

retournez à l'endroit où vous avez commencé avec

$ git rebase --abort

dites que votre histoire est

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a

C'est-à-dire, a était le premier commit, puis b, et finalement C. Après avoir commis c nous décidons d'écraser b et c ensemble:

(Note: git log pipes sa sortie dans un pager, less par défaut sur la plupart des plateformes. Pour quitter le pager et revenir à l'invite de commande, appuyez sur la touche q .)

Running git rebase --interactive HEAD~2 vous donne un éditeur avec

pick b76d157 b
pick a931ac7 c

# Rebase df23917..a931ac7 onto df23917
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

(notez que cette liste todo est dans l'ordre inverse par rapport à la sortie de git log .)

Modification b pick squash résultera dans l'erreur que vous avez vu, mais si au lieu de cela vous écrasez c dans b (nouveau commit dans l'ancien ou "squashing upward") en changeant la liste de todo en

pick   b76d157 b
squash a931ac7 c

et enregistrer-quitter votre éditeur, vous obtiendrez un autre éditeur dont le contenu est

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

b

# This is the 2nd commit message:

c

lorsque vous Enregistrez et quittez, le contenu du fichier édité devient commit message de la nouvelle propagation combinée:

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a

Note Sur La Réécriture Histoire

rebase Interactif réécrit l'histoire. Essayer de pousser vers une télécommande qui contient l'ancienne histoire échouera parce que ce n'est pas un fast-forward.

si la branche que vous avez rebasée est une branche de sujet ou de fonctionnalité dans laquelle vous travaillez par vous-même , pas grand chose. Pousser vers un autre dépôt exigera l'option --force , ou bien vous pourrez, selon les permissions du dépôt distant, supprimez d'abord l'ancienne branche, puis appuyez sur la version rebasée. Les exemples de commandes qui détruisent potentiellement le travail dépassent la portée de cette réponse.

réécrire l'histoire déjà publiée sur une branche dans laquelle vous travaillez avec d'autres personnes sans très bonne raison telle que la fuite d'un mot de passe ou d'autres détails sensibles force le travail sur vos collaborateurs et est antisocial et va ennuyer d'autres développeurs. Le Dans la section git rebase " documentation , la rubrique "Récupérer à partir d'un Rebase en amont" explique, en mettant l'accent sur ce point.

réécrire (ou toute autre forme de réécriture) une branche sur laquelle d'autres ont basé leur travail est une mauvaise idée: toute personne en aval de celle-ci est forcée de corriger manuellement son histoire. Cette section explique comment faire la correction du point de vue de l'aval. la vraie solution, cependant, serait d'éviter de rebaser l'amont dans le première place. ...

1562
répondu Greg Bacon 2018-08-01 23:03:34

S'il y a plusieurs commits, vous pouvez utiliser git rebase -i pour écraser deux commits en un.

S'il n'y a que deux propagations que vous voulez fusionner, et qu'elles sont les "deux plus récentes", Les commandes suivantes peuvent être utilisées pour combiner les deux propagations en une seule:

git reset --soft "HEAD^"
git commit --amend
347
répondu user3828059 2015-08-05 21:42:47

Rebase: Vous ne Va pas avoir Besoin:

une façon plus simple pour le scénario le plus fréquent.

dans la plupart des cas:

en fait si tout ce que vous voulez est juste simplement fusionner plusieurs commits récents dans un mais n'ont pas besoin drop , reword et d'autres travaux de rebase.

, vous pouvez simplement faire:

git reset --soft "HEAD~n"
  • en supposant que ~n est nombre de commits à un-commit (i.e. ~1 , ~2 ,...)

ensuite, utilisez la commande suivante pour modifier le message de propagation.

git commit --amend

qui est assez semblable à une longue portée de squash et un pick .

et il fonctionne pour n commits mais pas seulement deux commits comme ci-dessus réponse incité.

58
répondu pambda 2017-12-26 14:55:20

vous devez d'abord vérifier combien de commits vous avez:

git log

il y a deux statuts:

l'Un est qu'il y a seulement deux commits:

par exemple:

commit A
commit B

(dans ce cas, vous ne pouvez pas utiliser git rebase pour faire) vous devez faire ce qui suit.

$ git reset --soft HEAD^1

$ git commit --amend

un autre est qu'il y a plus de deux commits; vous voulez fusionner commit C et D.

par exemple:

commit A
commit B
commit C
commit D

(sous cette condition, vous pouvez utiliser git rebase)

git rebase -i B

et que d'utiliser" squash " à faire. Le reste s'amincit est très facile. Si vous ne savez toujours pas, s'il vous plaît lire http://zerodie.github.io/blog/2012/01/19/git-rebase-i /

51
répondu Haimei 2014-05-27 19:01:46

en supposant que vous étiez dans votre propre branche. Si vous souhaitez fusionner les 2 derniers s'engage dans l'une et ressembler à un héros, branche de l'engager juste avant les deux derniers commits.

git checkout -b temp_branch HEAD^2

Puis squash commettre l'autre branche de cette nouvelle branche:

git merge branch_with_two_commits --squash

qui introduira les changements mais ne les commettra pas. Donc suffit de les engager et vous avez terminé.

git commit -m "my message"

maintenant vous pouvez fusionner ce nouveau sujet branche dans votre branche principale.

26
répondu Homan 2015-08-26 20:08:20

vous pouvez annuler le rebase avec

git rebase --abort

et quand vous lancez à nouveau la commande de rebase interactive, le ' squash; commit doit être en dessous du pick commit dans la liste

22
répondu Leom Burke 2010-04-01 20:59:48

j'utilise souvent git reset --mixte pour revenir à une version de base avant plusieurs engage lequel vous souhaitez fusionner, puis-je faire un nouveau commit qui pourrait laisser vos commettre de nouveau, de s'assurer que votre version est à la TÊTE après que vous appuyez sur le serveur.

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

si je veux fusionner la tête deux commet en une, d'abord j'utilise :

git reset --mixed 249cf9392da197573a17c8426c282

"249cf9392da197573a17c8426c282" était la troisième version, est également votre version de base avant votre fusion, après cela, je fais un nouveau commit:

git add .
git commit -m 'some commit message'

c'est tout, l'espoir est un autre moyen pour tout le monde.

pour info, à partir de git reset --help :

 --mixed
     Resets the index but not the working tree (i.e., the changed files are
     preserved but not marked for commit) and reports what has not been
     updated. This is the default action.
13
répondu VinceStyling 2015-03-18 15:03:39

$ git rebase --abort

exécutez ce code à tout moment si vous voulez annuler le git rebase

$ git rebase -i HEAD~2

pour réappliquer les deux dernières commits. La commande ci-dessus ouvrira un éditeur de code

  • [ Le dernier commit sera en bas ]. Modifier la dernière s'engager à la courge(s). Puisque squash va fusionner avec la propagation précédente.
  • appuyez ensuite sur esc key et tapez :wq pour enregistrer et fermer

après: wq vous serez en mode actif rebase

Note : vous obtiendrez un autre éditeur si aucun message d'avertissement / erreur, S'il y a une erreur ou un avertissement qu'un autre éditeur ne montrera pas, vous pouvez annuler en lançant $ git rebase --abort si vous voyez une erreur ou un avertissement, continuez simplement en exécutant $ git rebase --continue

You allez voir votre 2 message de commit. Choisissez un ou écrire votre propre message de commit, sauvegarder et quitter [:wq]

Note 2:

$ git push -f

$ git push -f origin master

11
répondu Gnanasekar S 2017-02-20 21:54:51

si votre branche principale git log ressemble à quelque chose comme suit:

commit ac72a4308ba70cc42aace47509a5e
Author: <me@me.com>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <me@me.com>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <ralph@me.com>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

et vous voulez fusionner les deux premières propagations il suffit de suivre les étapes faciles:

  1. le premier à être sur safe side checkout le second dernier commit dans une branche séparée. Vous pouvez nommer la branche n'importe quoi. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. maintenant, choisissez vos changements de la dernière commit dans cette nouvelle branche comme: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e . (Résoudre conflits éventuels)
  3. donc maintenant, vos changements dans la dernière propagation sont là dans votre dernière propagation. Mais vous devez tout de même commettre, donc d'abord ajouter les modifications que vous venez de sélectionner et ensuite exécuter git commit --amend .

C'est tout. Vous pouvez pousser cette version fusionnée dans la branche "merged-commits" si vous le souhaitez.

aussi, vous pouvez rejeter les deux commits dos-à-dos dans votre branche principale maintenant. Il suffit de mettre à jour votre branche principale as:

git checkout master
git reset --hard origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull
1
répondu Undefined 2013-06-16 15:57:34

puisque j'utilise git cherry-pick pour à peu près tout, pour moi il est naturel de le faire même ici.

étant donné que j'ai vérifié branchX et qu'il y a deux commits à la pointe de celui-ci, dont je veux créer un commit combinant leur contenu, je fais ceci:

git checkout HEAD^ // Checkout the privious commit
git cherry-pick --no-commit branchX // Cherry pick the content of the second commit
git commit --amend // Create a new commit with their combined content

Si je veux mettre à jour branchX (et je suppose que c'est l'inconvénient de cette méthode) j'ai aussi:

git checkout branchX
git reset --hard <the_new_commit>
1
répondu Martin G 2015-11-26 10:52:43

si vous voulez combiner les deux propagations les plus récentes et utiliser le message de l'ancienne propagation, vous pouvez automatiser le processus en utilisant expect .

je suppose:

  • Vous êtes à l'aide de vi comme votre éditeur de
  • vos commits sont d'une ligne chacun

j'ai essayé avec git version 2.14.3 (Apple Git-98) .


#!/usr/bin/env expect
spawn git rebase -i HEAD~2

# down, delete word, insert 's' (for squash), Escape, save and quit
send "jdwis 3:wq\r"

expect "# This is a"

# down 4, delete 3 lines, save and quit
send "4j3d\r:wq\r"

interact
0
répondu erwaman 2018-02-06 04:50:59