git reset
dreht sich alles um das Bewegen HEAD
, und im Allgemeinen ist der Zweig ref .
Frage: Was ist mit dem Arbeitsbaum und dem Index?
Bei Verwendung mit --soft
, bewegt sich HEAD
, aktualisiert meistens die Zweigreferenz und nur dieHEAD
.
Dies unterscheidet sich von commit --amend
:
- Es wird kein neues Commit erstellt.
- Es kann HEAD tatsächlich in ein beliebiges Commit verschieben (da
commit --amend
es nur darum geht , HEAD nicht zu verschieben, während das aktuelle Commit wiederholt werden kann).
Ich habe gerade dieses Beispiel für das Kombinieren gefunden:
- eine klassische Verschmelzung
- eine Teilbaumzusammenführung
Alles in einem (Octopus, da mehr als zwei Zweige zusammengeführt werden) Commit Merge.
Tomas "wereHamster" Carnecky erklärt in seinem Artikel "Subtree Octopus Merge" :
- Die Strategie zum Zusammenführen von Teilbäumen kann verwendet werden, wenn Sie ein Projekt in ein Unterverzeichnis eines anderen Projekts zusammenführen und anschließend das Teilprojekt auf dem neuesten Stand halten möchten. Es ist eine Alternative zu Git-Submodulen.
- Mit der Octopus-Merge-Strategie können drei oder mehr Zweige zusammengeführt werden. Die normale Strategie kann nur zwei Zweige zusammenführen. Wenn Sie versuchen, mehr als das zusammenzuführen, greift git automatisch auf die Octopus-Strategie zurück.
Das Problem ist, dass Sie nur eine Strategie auswählen können. Aber ich wollte beide kombinieren, um einen sauberen Verlauf zu erhalten, in dem das gesamte Repository atomar auf eine neue Version aktualisiert wird.
Ich habe ein Superprojekt, nennen wir es projectA
, und ein Unterprojekt projectB
, das ich in ein Unterverzeichnis von zusammengeführt habe projectA
.
(das ist der Teilbaum-Zusammenführungsteil)
Ich halte auch ein paar lokale Verpflichtungen aufrecht.
ProjectA
wird regelmäßig aktualisiert, projectB
hat alle paar Tage oder Wochen eine neue Version und hängt normalerweise von einer bestimmten Version von ab projectA
.
Wenn ich mich entscheide, beide Projekte zu aktualisieren, ziehe ich nicht einfach ab projectA
und projectB
da dies zwei Commits für ein atomares Update des gesamten Projekts erzeugen würde .
Stattdessen erstelle ich ein einzelnes Merge-Commit, das kombiniert wird projectA
, projectB
und meine lokalen Commits .
Der schwierige Teil hier ist, dass dies eine Octopus-Zusammenführung (drei Köpfe) ist, aber projectB
mit der Teilbaumstrategie zusammengeführt werden muss . Das mache ich also:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
Hier verwendete der Autor a reset --hard
und stellte dann read-tree
wieder her, was die ersten beiden Zusammenführungen mit dem Arbeitsbaum und dem Index bewirkt hatten. Hier reset --soft
kann jedoch
Folgendes hilfreich sein: Wie kann ich die beiden Zusammenführungen wiederholen , die funktioniert haben, dh mein Arbeitsbaum und mein Index sind gut, aber ohne diese beiden Commits aufzeichnen zu müssen?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Jetzt können wir Tomas 'Lösung wieder aufnehmen:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
Also jedes Mal:
- Sie sind zufrieden mit dem, was Sie am Ende haben (in Bezug auf Arbeitsbaum und Index).
- Sie sind nicht zufrieden mit all den Verpflichtungen, die Sie dorthin gebracht haben:
git reset --soft
ist die Antwort.
git reset --soft
: stackoverflow.com/questions/6869705/…Anwendungsfall - Kombinieren Sie eine Reihe lokaler Commits
"Ups. Diese drei Commits könnten nur eine sein."
Machen Sie also die letzten 3 (oder was auch immer) Commits rückgängig (ohne den Index oder das Arbeitsverzeichnis zu beeinflussen). Übernehmen Sie dann alle Änderungen als eine.
Z.B
Jetzt bleiben alle Ihre Änderungen erhalten und können als eine festgeschrieben werden.
Kurze Antworten auf Ihre Fragen
Sind diese beiden Befehle wirklich gleich (
reset --soft
vscommit --amend
)?Gibt es einen Grund, das eine oder andere praktisch zu verwenden?
commit --amend
Hinzufügen von / rm-Dateien aus dem allerletzten Commit oder Ändern der Nachricht.reset --soft <commit>
mehrere sequentielle Commits zu einem neuen zu kombinieren.Und was noch wichtiger ist: Gibt es
reset --soft
außer der Änderung eines Commits noch andere Verwendungszwecke ?quelle
reset --soft
git reset
) gut sind, wenn Sie (a) den Verlauf neu schreiben möchten, (b) sich nicht um die alten Commits kümmern (damit Sie die Aufregung des interaktiven Rebases vermeiden können) und (c) mehr als ein Commit zur Änderung haben (ansonstencommit --amend
ist es einfacher).Ich verwende es, um mehr als nur das letzte Commit zu ändern .
Nehmen wir an, ich habe einen Fehler in Commit A gemacht und dann Commit B gemacht. Jetzt kann ich nur noch B ändern
git reset --soft HEAD^^
.Natürlich ist es für große Commits nicht sehr praktisch… aber du solltest sowieso keine großen Commits machen ;-)
quelle
git commit --fixup HEAD^^
git rebase --autosquash HEAD~X
funktioniert auch gut.git rebase --interactive HEAD^^
Hier können Sie die Commits A und B bearbeiten. Auf diese Weise bleiben die Commit-Nachrichten von A und B erhalten. Bei Bedarf können Sie diese auch noch ändern.git reset A
machen , und fügen Sie Änderungengit commit --amend
,git cherry-pick <B-commit-hash>
.Eine andere mögliche Verwendung ist eine Alternative zum Verstecken (was manche Leute nicht mögen, siehe z . B. https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ ).
Wenn ich zum Beispiel an einem Zweig arbeite und dringend etwas am Master reparieren muss, kann ich einfach Folgendes tun:
dann checkout master und mach das fix. Wenn ich fertig bin, kehre ich zu meiner Filiale zurück und mache es
weiterarbeiten, wo ich aufgehört habe.
quelle
--soft
ist hier eigentlich unnötig, es sei denn, Sie möchten wirklich, dass die Änderungen sofort bereitgestellt werden. Ich benutze jetzt nur,git reset HEAD~
wenn ich das mache. Wenn ich einige Änderungen haben statt wenn ich brauche Zweige zu wechseln, und wollen es auch bleiben, dann mache ichgit commit -m "staged changes"
, danngit commit -am "unstaged changes"
, spätergit reset HEAD~
gefolgt vongit reset --soft HEAD~
vollständig den Arbeitszustand wiederherzustellen. Obwohl, um ehrlich zu sein, ich diese beiden Dinge jetzt, wo ich weiß, viel wenigergit-worktree
Sie können
git reset --soft
die Version ändern, die Sie als übergeordnetes Element für die Änderungen in Ihrem Index und Arbeitsbaum haben möchten. Die Fälle, in denen dies nützlich ist, sind selten. Manchmal können Sie entscheiden, dass die Änderungen, die Sie in Ihrem Arbeitsbaum haben, zu einem anderen Zweig gehören sollen. Oder Sie können dies als einfache Methode verwenden, um mehrere Commits zu einem zusammenzufassen (ähnlich wie Squash / Fold).In dieser Antwort von VonC finden Sie ein praktisches Beispiel: Squash die ersten beiden Commits in Git?
quelle
git reset --soft anotherBranch
und verpflichte mich dort? Aber Sie ändern den Ckeckout-Zweig nicht wirklich. Werden Sie sich also für den Zweig oder eine andere Branche entscheiden ?Eine mögliche Verwendung wäre, wenn Sie Ihre Arbeit auf einem anderen Computer fortsetzen möchten. Es würde so funktionieren:
Kasse einer neuen Filiale mit einem versteckten Namen,
Schieben Sie Ihren Stash-Zweig nach oben,
Wechseln Sie zu Ihrem anderen Computer.
Ziehen Sie sowohl Ihren Vorrat als auch die vorhandenen Zweige herunter.
Sie sollten sich jetzt in Ihrer bestehenden Niederlassung befinden. Führen Sie die Änderungen aus dem Stash-Zweig zusammen.
Setzen Sie Ihren vorhandenen Zweig vor dem Zusammenführen auf 1 zurück.
Entfernen Sie Ihren Versteckzweig,
Entfernen Sie auch Ihren Stash-Zweig vom Ursprung.
Arbeiten Sie weiter mit Ihren Änderungen, als hätten Sie sie normal aufbewahrt.
Ich denke, in Zukunft werden GitHub und Co. sollte diese "Remote Stash" -Funktionalität in weniger Schritten anbieten.
quelle
Eine praktische Anwendung ist, wenn Sie sich bereits für Ihr lokales Repo entschieden haben (z. B. git commit -m), können Sie dieses letzte Commit durch Zurücksetzen von git --soft HEAD ~ 1 rückgängig machen
Auch für Ihr Wissen, wenn Sie Ihre Änderungen bereits inszeniert haben (dh mit git add.), Können Sie die Inszenierung umkehren, indem Sie git reset --mixed HEAD ausführen, oder ich habe gewöhnlich auch nur verwendet
git reset
Zuletzt löscht git reset --hard alles aus, einschließlich Ihrer lokalen Änderungen. Der ~ after-Kopf gibt an, zu wie vielen Commits Sie von oben gehen müssen.
quelle
git reset --soft HEAD ~1
gebe ichfatal: Cannot do soft reset with paths.
mir denke , dass wir den Raum nach HEAD entfernen müssen , so dass es sein würdegit reset --soft HEAD~1
Ein guter Grund, '
git reset --soft <sha1>
' zu verwenden, ist, sichHEAD
in einem nackten Repo zu bewegen .Wenn Sie versuchen, die Option
--mixed
oder zu verwenden--hard
, wird eine Fehlermeldung angezeigt, da Sie versuchen, einen nicht vorhandenen Baum und / oder Index zu ändern und zu bearbeiten.Hinweis: Sie müssen dies direkt vom Bare Repo aus tun.
Hinweis: Sie müssen sicherstellen, dass der Zweig, den Sie im Bare Repo zurücksetzen möchten, der aktive Zweig ist. Wenn nicht, befolgen Sie die Antwort von VonC zum Aktualisieren des aktiven Zweigs in einem Bare-Repo, wenn Sie direkten Zugriff auf das Repo haben.
quelle
SourceTree ist eine Git-GUI mit einer recht praktischen Oberfläche, auf der Sie genau die gewünschten Bits bereitstellen können. Es gibt nichts Ähnliches für die Änderung einer ordnungsgemäßen Überarbeitung.
Ist
git reset --soft HEAD~1
also viel nützlicher alscommit --amend
in diesem Szenario. Ich kann das Commit rückgängig machen, alle Änderungen wieder in den Staging-Bereich übertragen und die bereitgestellten Bits mit SourceTree weiter optimieren.Wirklich, es scheint mir, dass dies
commit --amend
der redundantere Befehl der beiden ist, aber git ist git und scheut sich nicht vor ähnlichen Befehlen zurück, die etwas andere Dinge tun.quelle
Obwohl mir die Antworten in diesem Thread
git reset --soft
sehr gut gefallen, verwende ich sie für ein etwas anderes, aber dennoch sehr praktisches Szenario.Ich verwende eine IDE für die Entwicklung, die ein gutes Diff-Tool zum Anzeigen von Änderungen (inszeniert und nicht inszeniert) nach meinem letzten Commit enthält. Jetzt beinhalten die meisten meiner Aufgaben mehrere Commits. Nehmen wir zum Beispiel an, ich mache 5 Commits, um eine bestimmte Aufgabe zu erledigen. Ich verwende das Diff-Tool in der IDE während jedes inkrementellen Commits von 1 bis 5, um meine Änderungen gegenüber dem letzten Commit zu überprüfen. Ich finde es sehr hilfreich, meine Änderungen vor dem Festschreiben zu überprüfen.
Wenn ich jedoch am Ende meiner Aufgabe alle meine Änderungen zusammen (vor dem ersten Festschreiben) anzeigen möchte, um vor dem Abrufen einer Pull-Anforderung eine Selbstcodeüberprüfung durchzuführen, werden nur die Änderungen aus meinem vorherigen Festschreiben (nach dem Festschreiben) angezeigt 4) und nicht von allen Commits meiner aktuellen Aufgabe geändert.
Also
git reset --soft HEAD~4
gehe ich 4 Commits zurück. Dadurch kann ich alle Änderungen zusammen sehen. Wenn ich von meinen Änderungen überzeugt bin, kann ichgit reset HEAD@{1}
sie sicher auf die Fernbedienung übertragen.quelle
git add --patch
undgit commit
wiederholt, um die Commit-Serie zu erstellen, die Sie erstellt hätten, wenn Sie gewusst hätten, was Sie die ganze Zeit getan haben. Ihre ersten Verpflichtungen sind wie die Notizen auf Ihrem Schreibtisch oder der erste Entwurf eines Memos. Sie dienen dazu, Ihr Denken zu organisieren und nicht zur Veröffentlichung.git reset @{1}
Ihre erste Entwurfsreihe wiederherzustellen, können Sie stattdessen eine Reihe für Veröffentlichungen ausgit add -p
und erstellengit commit
.Ein anderer Anwendungsfall ist, wenn Sie den anderen Zweig in einer Pull-Anfrage durch Ihren ersetzen möchten. Nehmen wir beispielsweise an, Sie haben eine Software mit den Funktionen A, B, C in der Entwicklung.
Sie entwickeln mit der nächsten Version und Sie:
Funktion B entfernt
Feature D hinzugefügt
Entwickeln Sie dabei gerade hinzugefügte Hotfixes für Feature B.
Sie können die Entwicklung in die nächste zusammenführen, aber das kann manchmal chaotisch sein, aber Sie können auch
git reset --soft origin/develop
ein Commit mit Ihren Änderungen verwenden und erstellen, und der Zweig kann ohne Konflikte zusammengeführt werden und Ihre Änderungen beibehalten.Es stellt sich heraus, dass dies
git reset --soft
ein praktischer Befehl ist. Ich persönlich benutze es häufig, um Commits zu quetschen, die keine "abgeschlossene Arbeit" wie "WIP" haben. Wenn ich also die Pull-Anfrage öffne, sind alle meine Commits verständlich.quelle