J'essaie de fusionner 2 commits en 1, alors j'ai suivi "écraser commets avec rebase" de git ready .
J'ai couru
git rebase --interactive HEAD~2
Dans l'éditeur résultant, je remplace pick
par squash
, puis enregistrez-quit, mais la base est défaillante avec l'erreur
Impossible de 'squash' sans un commit précédent
Maintenant que mon arbre de travail a atteint cet état, je ne parviens pas à récupérer. La commande git rebase --interactive HEAD~2
échoue avec
Rebase interactive déjà commencé
et git rebase --continue
échoue avec
Impossible de 'squash' sans un commit précédent
Le message d'erreur
Impossible de 'squash' sans un commit précédent
Git écrase toujours un nouveau commit dans un commit plus ancien ou "vers le haut" tel qu'il est affiché dans la liste de tâches interactive de base , c’est-à-dire un commit sur une ligne précédente. Changer la commande de la toute première ligne de votre liste de tâches en squash
produira toujours cette erreur car il n’ya rien dans le premier commit à écraser.
D'abord, retournez à votre point de départ
$ git rebase --abort
Dis que ton histoire est
$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a
C'est-à-dire que a était le premier commit, puis b et enfin c. Après avoir commis c, nous décidons d’écraser b et c ensemble:
(Remarque: l'exécution de git log
transfère sa sortie dans un pager, less
par défaut sur la plupart des plates-formes. Pour quitter le pageur et revenir à l'invite de commande, appuyez sur la touche Touche q
.)
Lancer 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 de tâches est dans l'ordre inverse de la sortie de git log
.)
Si vous changez pick
de b en squash
, vous obtiendrez l’erreur que vous avez constatée, mais si vous écrasez c en b (nouvelle commande plus ancienne ou plus ancienne) en modifiant la liste de tâches en
pick b76d157 b
squash a931ac7 c
et en quittant votre éditeur, vous aurez 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 modifié devient un message de validation du nouveau commit combiné:
$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a
Rebase interactive réécrit l'histoire. Toute tentative d'envoi à une télécommande qui contient l'ancien historique échouera car il ne s'agit pas d'une avance rapide.
Si la branche que vous rebasez est une branche de sujet ou de fonctionnalité dans laquelle vous travaillez seul , ce n'est pas grave. Pousser vers un autre référentiel nécessitera l’option --force
, ou vous pourrez éventuellement, en fonction des autorisations du référentiel distant, supprimer d’abord l’ancienne branche puis Transférer la version rebasée. Des exemples de commandes susceptibles de détruire du travail n'entrent pas dans le cadre de cette réponse.
Réécrire l’historique déjà publié sur une branche dans laquelle vous travaillez avec d’autres personnes sans de très bonnes raisons, telles que la divulgation d’un mot de passe ou d’autres données confidentielles, obligent ainsi vos collaborateurs à travailler de manière antisociale. va déranger les autres développeurs. La section "Récupération à partir d'une base amont" dans la documentation git rebase
explique, avec une emphase supplémentaire.
Redéfinir la base (ou toute autre forme de réécriture) d'une branche sur laquelle d'autres ont travaillé est une mauvaise idée: toute personne en aval de celle-ci est obligée de corriger manuellement son historique. Cette section explique comment effectuer le correctif du point de vue de l’aval. La vraie solution, cependant, serait d'éviter de rebasonner l'upstream en premier lieu. …
S'il existe plusieurs validations, vous pouvez utiliser git rebase -i
pour réduire deux validations en une seule.
S'il n'y a que deux commits que vous souhaitez fusionner et qu'il s'agit des "deux plus récents", vous pouvez utiliser les commandes suivantes pour combiner les deux commits en un:
git reset --soft "HEAD^"
git commit --amend
Un moyen plus simple pour le scénario le plus fréquent.
En fait, si tout ce que vous voulez est juste combinez simplement plusieurs commits récents en un mais n'avez pas besoin de drop
, reword
et d'autres travaux de rebase.
git reset --soft "HEAD~n"
~n
soit le nombre de commits pour annuler la validation doucement (c.-à-d. ~1
, ~2
, ...)Ensuite, utilisez la commande suivante pour modifier le message de validation.
git commit --amend
ce qui est à peu près la même chose qu'une longue plage de squash
et un pick
.
Et cela fonctionne pour n commits mais pas seulement deux commits, comme indiqué ci-dessus.
Tout d’abord, vous devriez vérifier le nombre de commits que vous avez:
git log
Il y a deux statut:
Le premier est qu’il n’ya que deux commits:
Par exemple:
commit A
commit B
(Dans ce cas, vous ne pouvez pas utiliser git rebase à faire), vous devez suivre les instructions suivantes.
$ git reset --soft HEAD^1
$ git commit --amend
Une autre est qu'il y a plus de deux commits; vous voulez fusionner les commit C et D.
Par exemple:
commit A
commit B
commit C
commit D
(dans cette condition, vous pouvez utiliser git rebase)
git rebase -i B
Et que d'utiliser "squash" à faire. Le reste est très facile. Si vous ne le savez toujours pas, veuillez lire http://zerodie.github.io/blog/2012/01/19/git-rebase-i/
En supposant que vous êtes dans votre propre branche de sujet. Si vous souhaitez fusionner les 2 derniers commits en un et ressembler à un héros, déconnectez-vous du commit juste avant de faire les deux derniers commits.
git checkout -b temp_branch HEAD^2
Ensuite, squash engage l’autre branche de cette nouvelle branche:
git merge branch_with_two_commits --squash
Cela apportera les changements mais ne les engagera pas. Alors, engagez-les et vous avez terminé.
git commit -m "my message"
Vous pouvez maintenant fusionner cette nouvelle branche de sujet dans votre branche principale.
vous pouvez annuler la rebase avec
git rebase --abort
et lorsque vous exécutez à nouveau la commande interactive rebase, le 'squash'; commit doit être inférieur au pick commit dans la liste
J'utilise souvent git reset --mixed pour rétablir une version de base avant plusieurs validations que vous souhaitez fusionner, puis je fais une nouvelle validation, de cette façon, vous pouvez laisser votre commit le plus récent, assurez-vous que votre version est HEAD après avoir poussé vers le serveur.
commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date: Tue Jun 11 10:23:07 2013 +0500
Added algorithms for Cosine-similarity
commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date: Tue Jun 11 13:02:14 2013 -0700
Set stage for similar objects
commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date: Thu Jun 13 16:44:12 2013 -0700
Fixed a bug in space world automation
Si je veux fusionner deux commits en un, j'utilise d'abord:
git reset --mixed 249cf9392da197573a17c8426c282
"249cf9392da197573a17c8426c282" était la troisième version, c'est aussi votre version de base avant de fusionner, 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.
FYI, 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.
$ git rebase --abort
Exécutez ce code à tout moment si vous voulez annuler la rebase git
$ git rebase -i HEAD~2
Réappliquer les deux derniers commits. La commande ci-dessus ouvrira un éditeur de code
Après: wq vous serez en mode rebase actif
Remarque : Vous aurez un autre éditeur si aucun message d'avertissement/d'erreur ne s'affiche, S'il y a une erreur ou si un autre éditeur est averti pas montré, vous pouvez abandonner en exécutant $ git rebase --abort
si vous voyez une erreur ou un avertissement, continuez simplement en exécutant $ git rebase --continue
Vous verrez votre message 2 commit. Choisissez-en un ou écrivez votre propre message de validation, sauvegardez et quittez [: wq]
Remarque 2: Vous devrez peut-être forcer la transmission de vos modifications au référentiel distant si vous exécutez la commande rebase.
$ git Push -f
$ git Push -f Origin master
Puisque j'utilise git cherry-pick
pour à peu près tout, il m'est naturel de le faire même ici.
Étant donné que j’ai branchX
vérifié et qu’il y a deux commits, dont je veux créer un, 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
aussi (et je suppose que c'est le côté négatif de cette méthode), je dois aussi:
git checkout branchX
git reset --hard <the_new_commit>
Si vous souhaitez combiner les deux derniers commits et utiliser simplement le message de l'ancien, vous pouvez automatiser le processus à l'aide de expect
.
Je suppose:
J'ai testé 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 \033:wq\r"
expect "# This is a"
# down 4, delete 3 lines, save and quit
send "4j3d\r:wq\r"
interact
Si votre branche principale git log
ressemble à ce qui suit:
commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date: Tue Jun 11 10:23:07 2013 +0500
Added algorithms for Cosine-similarity
commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date: Tue Jun 11 13:02:14 2013 -0700
Set stage for similar objects
commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date: Thu Jun 13 16:44:12 2013 -0700
Fixed a bug in space world automation
et vous voulez fusionner les deux commits les plus importants, procédez comme suit:
git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e
. (Résoudre les conflits s'il en survient)git commit --amend
.C'est ça. Vous pouvez pousser cette version fusionnée dans la branche "fusionnée-validée" si vous le souhaitez.
En outre, vous pouvez maintenant ignorer les deux commits consécutifs dans votre branche principale. Il suffit de mettre à jour votre branche principale en tant que:
git checkout master
git reset --hard Origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull