27 Stimmen

git: squash/fixup frühere Übergabe

Angenommen, Sie haben:

A-B-C

Jetzt schlägt Ihr Build/Test fehl. Der Fix sollte in A eingefügt werden. Mein derzeitiger Arbeitsablauf ist wie folgt:

$ git commit -m "fixA"

A-B-C-fixA

$ git rebase -i A~1

Und Squash fixA in A, ergeben:

A'-B-C

Gibt es einen Befehl, mit dem man so etwas tun kann:

A-B-C + (index with fix for A)

$ git commit -supperdupper A 

Ergebnis:

A'-B-C

1 Stimmen

Warum diese seltsame Anforderung, dass fixA in A zusammengeführt werden muss?

12 Stimmen

Weil es von vornherein in A hätte stehen müssen.

4 Stimmen

Ich tue dasselbe; ich weiß nicht, warum die Leute das für seltsam halten. Wenn Sie versuchen, Commits in kleine, logisch gruppierte Teile zu organisieren, dann ist es natürlich, dass Sie mehrere unveröffentlichte Commits gleichzeitig vorbereiten. (Man weiß vielleicht nicht, ob man wirklich mit A fertig ist, bis man C fertig hat).

21voto

Jo Liss Punkte 27127

Wenn Sie nur nach einer einfachen Lösung suchen, um frühere Übertragungen zu korrigieren, lesen Sie die Frage! Dort wird alles erklärt. Aber da Elmarco nach einem eleganten Weg gefragt hat, hier ist er:

Seit Git 1.7.0 gibt es eine --autosquash Option für rebase die genau das tut, was Sie wollen. Es gibt auch die --fixup y --squash Optionen für commit um die Dinge zu erleichtern. Mit etwas Aliasing können Sie das Ganze wahrscheinlich sogar in einem einzigen Befehl unterbringen.

Ich würde vorschlagen, auf die neueste Git-Version zu aktualisieren, um den größtmöglichen Nutzen zu erzielen:

git/Documentation/RelNotes $ grep -i -A1 autosquash\\\|fixup *
1.7.0.txt: * "git rebase -i" learned new action "fixup" that squashes the change
1.7.0.txt-   but does not affect existing log message.
--
1.7.0.txt: * "git rebase -i" also learned --autosquash option that is useful
1.7.0.txt:   together with the new "fixup" action.
1.7.0.txt-
--
1.7.3.txt: * "git rebase -i" peeks into rebase.autosquash configuration and acts as
1.7.3.txt:   if you gave --autosquash from the command line.
1.7.3.txt-
--
1.7.4.txt: * "git commit" learned --fixup and --squash options to help later invocation
1.7.4.txt-   of the interactive rebase.
--
1.7.4.txt: * "git rebase --autosquash" can use SHA-1 object names to name which
1.7.4.txt:   commit to fix up (e.g. "fixup! e83c5163").
1.7.4.txt-

2 Stimmen

5voto

bkeepers Punkte 1956

I einige Aliasnamen erstellt um die Verwendung der git commit --fixup y git commit --squash Befehle, die in git 1.7 hinzugefügt wurden. Fügen Sie diese zu Ihrem ~/.gitconfig :

[alias]
  fixup = !sh -c 'REV=$(git rev-parse $1) && git commit --fixup $@ && git rebase -i --autosquash $REV^' -
  squash = !sh -c 'REV=$(git rev-parse $1) && git commit --squash $@ && git rebase -i --autosquash $REV^' -

Verwendung:

$ git commit -am 'bad commit'
$ git commit -am 'good commit'

$ git add .          # Stage changes to correct the bad commit
$ git fixup HEAD^    # HEAD^ can be replaced by the SHA of the bad commit

Der fehlerhafte Commit kann mehrere Commits zurück liegen.

0 Stimmen

Die Verwendung Ihres Fixup-Alias funktioniert hervorragend. Durch das Hinzufügen von --autostash, ist es perfekt.

4voto

Mika Eloranta Punkte 416

Mein derzeitiger Git-Arbeitsablauf sieht folgendermaßen aus --fixup / --squash intensiv, dass ich ein neues git-fixup Befehl, der die meisten der lästigen Bits automatisch erledigt:

  • git fixup zeigt die geänderten Dateien an, die unter den letzten Commits gruppiert sind, die die gleiche Dateien
  • git fixup -a überträgt all diese Änderungen als --fixup Änderungen mit ihren entsprechenden "übergeordneten" Übertragungen
  • git fixup -r macht eine automatische git rebase --autosquash für alle Fixup-Commits

Viele Änderungen sind so beschaffen, dass die drei oben genannten Befehle ausreichen, um die Arbeit zu erledigen, ohne das Kopieren und Einfügen von Commit-IDs oder das Durchlesen der git log das Richtige zu finden --fixup Ziele.

Quelle: https://github.com/ohmu/git-crust

2voto

lanoxx Punkte 10439

Wenn Sie die letzten beiden Commits zerstören wollen, müssen Sie die

git rebase --interactive <3rd last commit>

Sie müssen dann den letzten Commit auswählen und den vorletzten Commit zerdrücken. Sie können den obersten Commit einer Historie nicht löschen.

0voto

Martin OConnor Punkte 3546

Was Sie tun, ist gefährlich, wenn Sie den Zweig, an dem Sie Änderungen vornehmen, mit anderen Personen teilen. In Ihrem Fall sind Sie Umschreiben A zu übertragen und B und C auf dem neuen A, das ein völlig neues Objekt ist, neu zu basieren. Jeder, der bereits das alte A in sein Repository gezogen hat, könnte sein Repository beschädigen, da sich der Verlauf in Ihrem Repository "auf magische Weise" geändert hat. Ihr Git hätte keine Möglichkeit zu wissen, dass die Historie umgeschrieben worden ist.

Aus diesem Grund haben die Git-Entwickler dies absichtlich nicht so einfach gemacht, da Sie sich der Konsequenzen eines solchen Vorgangs bewusst sein müssen.

4 Stimmen

Ich bin mir der Konsequenzen bewusst, ich möchte diese Verpflichtungen nicht teilen.

2 Stimmen

Tatsächlich ist die Git-Datei des anderen Entwicklers würde wissen, dass sich die Geschichte geändert hatte. Das Repository-Format von Git garantiert, dass man ein Repository auf diese Weise niemals "beschädigen" kann. Das Problem ist viel subtiler und das Git des Empfängers kann einen Haufen unnötiger Merge-Konflikte hervorrufen.

0 Stimmen

Das Problem ist hier dargestellt - kernel.org/pub/software/scm/git/docs/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X