Wie bewege ich mich zwischen Commits in Git vorwärts und rückwärts?

104

Ich mache ein git bisectund nachdem ich zu dem problematischen Commit gekommen bin, versuche ich jetzt, einen Schritt vorwärts / rückwärts zu machen, um sicherzustellen, dass ich im richtigen bin.

Ich weiß HEAD^, dass ich in der Geschichte rückwärts gehen muss, aber gibt es eine andere Abkürzung, um mich vorwärts zu bringen (in Richtung eines bestimmten Commits in der Zukunft), wie folgt:

A - B - C(HEAD) - D - E - F

Ich weiß, dass mein Ziel F ist und ich möchte von C nach D wechseln .


HINWEIS: Dies ist kein Duplikat von Git: Wie man zwischen Commits hin und her wechselt , meine Frage ist etwas anders und wird dort nicht beantwortet

Kostas
quelle
1
stackoverflow.com/questions/2263674/… kann ebenfalls helfen.
VonC
git checkout -b new_branch HEAD~44 Commits von HEAD wie in stackoverflow.com/a/4940090/911945
Anton Tarasenko

Antworten:

57

Ich habe ein bisschen experimentiert und dies scheint den Trick zu tun, um vorwärts zu navigieren ( Bearbeiten : Es funktioniert nur dann gut, wenn Sie einen linearen Verlauf ohne Zusammenführungs-Commits haben):

git checkout $(git rev-list --topo-order HEAD..towards | tail -1)

Wo towardsist ein SHA1 des Commits oder ein Tag.

Erläuterung:

  • Der Befehl inside $()bedeutet: Holen Sie sich alle Commits zwischen current HEADund towardscommit (ausgenommen HEAD) und sortieren Sie sie in der Rangfolge (wie git logstandardmäßig in - anstelle der chronologischen Reihenfolge, für die seltsamerweise die Standardeinstellung ist rev-list), und nehmen Sie dann die letzte ( tail), dh die, zu der wir gehen wollen.
  • Dies wird in der Subshell ausgewertet und an übergeben git checkout, um eine Prüfung durchzuführen.

Sie können eine Funktion definieren, auf die als Parameter erwartender Alias ​​in Ihrer .profileDatei zugegriffen werden kann, um vorwärts zum jeweiligen Commit zu navigieren:

# Go forward in Git commit hierarchy, towards particular commit 
# Usage:
#  gofwd v1.2.7
# Does nothing when the parameter is not specified.
gofwd() {
  git checkout $(git rev-list --topo-order HEAD.."$*" | tail -1)
}

# Go back in Git commit hierarchy
# Usage: 
#  goback
alias goback='git checkout HEAD~'
jakub.g
quelle
2
Das Vorwärtsgehen funktioniert gut in geraden Teilen der Geschichte, geht aber bei einer Zusammenführung in Schleifen über.
Kostas
Ja, ich habe es tatsächlich nicht bei Zusammenführungen getestet. Ich werde versuchen, in der Freizeit einen Blick darauf zu werfen, aber ich habe vorübergehend wenig Anreiz, da wir uns darauf geeinigt haben, eine streng lineare Geschichte in unserem Projekt zu haben;)
jakub.g
2
Gute Antwort! Geändert, um den aktuellen Zweig automatisch anzugeben: stackoverflow.com/a/23172256/480608
Raine Revere
Das ist falsch. git logZeigt Commits standardmäßig in chronologischer Reihenfolge an rev-list, außer bei Verwendung des --graphFlags.
Papiro
Ziemlich überzeugender Beweis dafür, dass Git zu komplex ist. Für etwas, das normalerweise so einfach ist wie Rückgängig oder Wiederherstellen, haben wir hier eine verrückte Liste widersprüchlicher Antworten. Und ich habe noch nicht einmal auf eine der verknüpften Antworten eingegangen. FWIW, ich habe eine Version davon mit einem einfachen linearen Satz von Commits ausprobiert und schließlich einfach aufgegeben.
Snowcrash
49

Alles, was Sie brauchen, um einen klaren, nicht abgelösten Kopfzustand zu erhalten, ist das Zurücksetzen und nicht das Auschecken.

git reset HEAD@{1}
d3day
quelle
5
oder git reset "HEAD@{1}"in bestimmten Muscheln wie Fisch und Powershell .. git reflogkann auch nützlich sein, um das richtige Commit zu finden.
Steve Cook
1
Verwenden Sie in Shell-Befehlen immer einfache Anführungszeichen, es sei denn, Sie möchten ausdrücklich, dass die Shell versucht, den Inhalt zu interpretieren / zu erweitern. Dies ist besonders wichtig in solchen Fällen, in denen das Ziel darin besteht, zu verhindern, dass die Shell Sonderzeichen interpretiert. Auf diese Weise müssen Sie nicht wissen, ob die Zeichenfolge problematische Elemente enthält.
Chris Seite
Ich habe das getan, um einen Blick zurück in die Zeit zu werfen, dann bin git reset HEADich zurückgegangen, wo ich war ... jetzt habe ich keine Ahnung, in welchem ​​Zustand sich mein Repository befindet und alles ist beängstigend. Was sollte ich jetzt tun?
theonlygusti
47

Ich glaube, Sie können tun:

git reset HEAD@{1}

Um ein Commit rechtzeitig voranzutreiben. Verwenden Sie HEAD @ {2}, HEAD @ {3} usw., um mehrere Commits fortzusetzen.

w0utert
quelle
20

Dies ist, was ich benutze, um hin und her zu navigieren.

Übergang zum nächsten Commit

function n() {
    git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}

Übergang zum vorherigen Commit

function p() {
    git checkout HEAD^1
}
MK
quelle
Vielen Dank! Ich benutze das jetzt! Hinweise für andere Anfänger wie mich : Um HEAD wieder anzubringen, wird git checkout <current branch>das neueste Commit angehängt. git checkout -b <new-branch-name>vom aktuellen Commit erlaubt Änderungen in neuem Zweig. git rebase -ifunktioniert auch. Außerdem habe ich meine n()Funktion so benannt nx(), dass Konflikte mit dem Node Version Manager "n" vermieden werden. Stellen Sie sicher, dass Sie die Aliase überprüfen!
Steven Choi
function () {...} dient zum Erstellen einer Unix / Linux-Bash-Skriptdatei. Ich komme aus Windows, was für mich zunächst schwer zu verstehen ist
IcyBrk,
funktioniert nicht = (.
Madeo
9

Angenommen, F ist das letzte Commit für trunk(geben Sie hier Ihren eigenen Filialnamen ein) ... Sie können es als trunk~0(oder nur trunk), E als trunk~1, D als trunk~2usw. bezeichnen.

Schauen Sie in Ihrem Reflog nach, wie Sie Commits benennen können.

Nutzlos
quelle
1
~ geht zurück, nicht vorwärts, Kofferraum ~ 2 ist A
EmmanuelMess
Ja. Bei dieser Antwort wird davon ausgegangen F, dass Sie einen Zweig namens "Trunk" haben, auf den Sie verweisen , und dass Sie wissen, wohin in der Geschichte dieses Zweigs Sie wechseln möchten. Es wird nicht versucht, sich relativ zum KOPF vorwärts zu bewegen, sondern relativ zum Rumpf weniger weit hinten.
Nutzlos
@ EmmanuelMess wie geht es trunk~2A?
theonlygusti
@theonlygusti Du bewegst dich zweimal von HEAD zurück.
EmmanuelMess
Sie gehen immer noch davon aus, dass der Zweig trunkund Ihr Strom HEADidentisch sind, was in der Frage nicht gezeigt wird, was ich angegeben habe, ist nicht das, was ich annehme, und was auf halbem Weg durch einenbisect
nutzlosen
3

Das Rückwärtsfahren ist trivial, da Sie sich den Baum hinunterbewegen und es immer einen Weg gibt

  function git_down
        git checkout HEAD^
  end

Wenn Sie vorwärts gehen, bewegen Sie sich den Baum hinauf, sodass Sie genau angeben müssen, auf welchen Zweig Sie abzielen:

  function git_up 
        git log --reverse --pretty=%H $argv | grep -A 1 (git rev-parse HEAD) | tail -n1 | xargs git checkout
  end

Verwendung : git down,git up <branch-name>

Dziamid
quelle
Das Zurückgehen ist auch bei Zusammenführungen nicht ganz einzigartig. Dies HEAD^ist jedoch normalerweise ein vernünftiger Standard.
kdb
2

Wenn Sie voraussehen möchten, können Sie diesen Trick ausführen, da Git keinen strengen Befehl dafür hat.

git log --reverse COMMIT_HASH..

Beispiel

Liste der Protokollverlaufs-Hashes:

A
B
C -> put this
D

mit dem Befehl git log --reverse C.., in der Ausgabe sehen Sie , B und A .

Dimpiax
quelle
1

Wahrscheinlich nicht der schönste Weg, aber Sie können git logdie Liste der Commits anzeigen und dann git checkout [sha1 of D]zu D wechseln.

BB-Generation
quelle
6
Ich verstehe es nicht, wenn er in C ist, dann zeigt Git Log ihm nur C, B und A.
Bilthon
Ok, verstanden, aber Sie müssen ein kniffliges Git-Log erstellen, wie es in dem von VonC
Bilthon
1

Ich habe gerade einen Test gemacht. Sagen Sie zum Beispiel, Sie befinden sich in der Hauptniederlassung. Dann tun Sie:

git checkout HEAD@{3}

Der Kopf löst sich also und Sie können es erneut versuchen, um zu einem anderen Commit zu gelangen:

git checkout HEAD@{4}

Sobald Sie sich umgesehen haben, können Sie zu Ihrem ursprünglichen Zustand zurückkehren, indem Sie einfach zu diesem Zweig auschecken. In meinem Beispiel: Hauptzweig

git checkout master

Wenn Sie nicht in den ursprünglichen Zustand zurückkehren möchten und daher eines der Commits als Kopf behalten und von dort aus fortfahren möchten, müssen Sie von dort aus verzweigen. Zum Beispiel nach "git checkout HEAD @ {4}" können Sie eine Ausgabe durchführen

git checkout -b MyNewBranch
user1322977
quelle
0

Um dieses Problem zu umgehen, können Sie einfach mit zu HEAD zurückkehren

git checkout <branch>

Wechseln Sie dann zu dem Commit, mit dem Sie möchten

git checkout HEAD~<offset>
Patrizio Bertoni
quelle
0

Wenn Sie vs-Code verwenden, ist der Git-Verlauf ein fantastisches Plugin, mit dem Sie Commits effizient anzeigen und deren Inhalt im Editor selbst überprüfen können. Überprüfen Sie den Link

Rahil Ahmad
quelle
0
branchName=master; commitInOrder=1; git checkout $(git log --pretty=%H "${branchName}" | tac | head -n "${commitInOrder}" | tail -n 1)

wo:

branchName entspricht dem Filialnamen

commitInOrder entspricht einem Commit in der Reihenfolge vom allerersten Commit in dem ausgewählten Zweig (also 1 ist das allererste Commit, 2 ist das zweite Commit im Zweig usw.)

Gast
quelle