Wie kann man Commits in Git quetschen, nachdem sie gedrückt wurden?

550

Dies gibt eine gute Erklärung für das Quetschen mehrerer Commits:

http://git-scm.com/book/en/Git-Branching-Rebasing

Es funktioniert jedoch nicht für Commits, die bereits gepusht wurden. Wie quetsche ich die letzten Commits sowohl in meinen lokalen als auch in meinen Remote-Repos?

BEARBEITEN: Wenn ich das tue git rebase -i origin/master~4 master, behalte den ersten als pick, setze die anderen drei als squashund beende dann (über cx cc in emacs), ich bekomme:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

Dabei ist 2f40 das pickCommit. Und jetzt erscheint keines der 4 Commits in git log. Ich habe erwartet, dass mein Editor neu gestartet wird, damit ich eine Commit-Nachricht eingeben kann. Was mache ich falsch?

Loren
quelle

Antworten:

779

Squash legt lokal mit fest

git rebase -i origin/master~4 master

und dann mit Gewalt drücken

git push origin +master

Unterschied zwischen --forceund+

Aus der Dokumentation von git push:

Beachten Sie, dass dies --forcefür alle Refs gilt, die gepusht werden. Wenn Sie es daher mit push.defaultfestgelegten matchingoder mit mehreren Push-Zielen verwenden, die mit konfiguriert sind, werden remote.*.pushmöglicherweise andere Refs als der aktuelle Zweig überschrieben (einschließlich lokaler Refs, die sich strikt hinter ihrem Remote-Gegenstück befinden). Um einen Push auf nur einen Zweig zu erzwingen, verwenden Sie ein + vor der Referenzspezifikation, um zu drücken (z. B. git push origin +masterum einen Push auf den masterZweig zu erzwingen ).

Alan Haggai Alavi
quelle
30
Sie können auchgit push --force origin master
Daenyth
7
Daenyth : Ja, aber ich bevorzuge immer diese Syntax, da diese kürzer ist.
Alan Haggai Alavi
86
Und natürlich sollten Sie sich darüber im Klaren sein, dass Sie dies wahrscheinlich nicht tun möchten, wenn jemand anderes aus dem Remote-Repository gezogen hat - die Antwort in diesem Fall lautet "Sie tun es nicht".
Cascabel
10
Ich denke auch, dass das OP den Befehl genau kopiert git rebase -i origin/masterund tatsächlich wissen möchte, wie Commits weiter zurückgesetzt werden können, z git rebase -i origin/master~20 master.
Cascabel
6
gstackoverflow : Erzwingt+ nur die Refspec, der ein Präfix vorangestellt ist. --forcewird erzwingen, dass alle Refspecs gedrückt werden. Bitte beachten Sie die aktualisierte Antwort.
Alan Haggai Alavi
120

Auf einem Zweig konnte ich das so machen (für die letzten 4 Commits)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch
jakob-r
quelle
1
Dies mit dem Soft-Befehl auf einem bereits geschobenen Zweig zu tun, führte dazu, dass eine Menge anderer Leute sich für mich engagierten.
Cchamberlain
3
Eine Tonne? Wie kann es mehr als 4 sein? Können Sie das näher erläutern?
Jakob-R
Das bin ich mir nicht sicher, aber es hatte etwas mit dem Versuch zu tun, ein bereits gedrängtes Commit zu unterdrücken. Sieht so aus, als hätten andere hier ähnliche Erfahrungen gemacht - stackoverflow.com/questions/5189560/…
cchamberlain
4
Ich hätte dies als erwartete Antwort akzeptiert. Sauberer als die akzeptierte Antwort.
Vikramvi
4
Dies ist die
klarste
45

Kleiner Unterschied zur akzeptierten Antwort, aber ich hatte große Schwierigkeiten beim Quetschen und bekam es schließlich.

$ git rebase -i HEAD~4
  • Ersetzen Sie auf dem sich öffnenden interaktiven Bildschirm Pick durch Squash oben für alle Commits, die Sie quetschen möchten.
  • Speichern und schließen Sie den Editor durch esc --> :wq

Drücken Sie auf die Fernbedienung mit:

$ git push origin branch-name --force
BLRBoy
quelle
2
kurz und effektiv, ausführlich:
Terwxqian
22

Viele Probleme lassen sich nur dadurch verhindert werden , eine zu schaffen , branchum die Arbeit an und nicht arbeiten master:

git checkout -b mybranch

Das Folgende funktioniert für remotebereits gepusste Commits und eine Mischung aus remotegeposteten Commits / localnur Commits:

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

Ich habe auch einige Pull-Request-Notizen, die hilfreich sein können.

Stuart Cardall
quelle
17

git rebase -i master

Sie werden den Editor vm geöffnet und msgs so etwas

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

Hier habe ich die Auswahl für alle anderen Commits auf "f" geändert (steht für Fixup).

git push -f origin feature/feature-branch-name-xyz

Dadurch werden alle Commits für ein Commit korrigiert und alle anderen Commits entfernt. Ich habe das getan und es hat mir geholfen.

Nupur
quelle
3

Wenn Sie mit einem Gitlab oder Github arbeiten, können Sie auf diese Weise Probleme bekommen. Sie quetschen Ihre Commits mit einer der oben genannten Methoden. Mein bevorzugter ist:

git rebase -i HEAD~4
or
git rebase -i origin/master

Wählen Sie Squash oder Fixup für Ihr Commit. An diesem Punkt würden Sie mit git Status überprüfen. Und die Nachricht könnte sein:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

Und Sie können versucht sein, es zu ziehen. TUN SIE DAS NICHT, sonst befinden Sie sich in der gleichen Situation wie zuvor.

Drücken Sie stattdessen zu Ihrem Ursprung mit:

git push origin +ABC-1916-remote:ABC-1916

Mit + können Sie nur einen Zweig erzwingen.

Alex
quelle
Es ist nichts Falsches am Ziehen, besonders wenn Sie Konflikte haben, können diese leichter gelöst werden, als wenn Sie Push erzwingen
Ray_Poly
2

Für das Quetschen von zwei Commits, von denen eines bereits verschoben wurde, auf einem einzelnen Zweig funktionierte Folgendes:

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

Standardmäßig enthält dies die Festschreibungsnachricht des neuesten Festschreibens als Kommentar zum älteren Festschreiben.

Hummerhände
quelle
2

1) git rebase -i HEAD~4

Um es näher zu erläutern: Es funktioniert in der aktuellen Branche. der KOPF ~ 4 bedeutet, die letzten vier Commits zu quetschen; interaktiver Modus (-i)

2) Zu diesem Zeitpunkt öffnete der Editor mit der Liste der Commits, um die zweiten und folgenden Commits zu ändern, indem er pick durch squash ersetzte und dann speicherte.

Ausgabe: Erfolgreich neu basiert und refs / Heads / Branch-Name aktualisiert.

3) git push origin refs/heads/branch-name --force

Ausgabe:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)
terwxqian
quelle