ref^
bezieht sich auf das Commit vor ref
, was ist mit dem Commit nach ref
?
Wenn ich zum Beispiel, git checkout 12345
wie überprüfe ich das nächste Commit?
Vielen Dank.
PS Ja, git ist ein DAG-Knotenzeiger-Strukturbaum. Wie finde ich das Commit nach diesem?
git
version-control
Schwern
quelle
quelle
git children-of
"!Antworten:
Um alle Commits aufzulisten, beginnend mit dem aktuellen und dann dem untergeordneten Commit usw. - im Grunde genommen ein Standard-Git-Log, aber mit der Zeit in die andere Richtung, verwenden Sie so etwas wie
Dabei ist 894e8b4e93d8f3 das erste Commit, das Sie anzeigen möchten.
quelle
HEAD^
für894e8b4e93d8f3^
....
,^..
scheitert lautlosfatal: unrecognized argument: --ancestry-path
in git Version 1.7.1master
sich der Stammpfad des aktuellen Commits befindet. Im zweiten Code-Snippet meiner Antwort finden Sie eine Lösung, die in allen Fällen funktioniert.Der Schöpfer von Hudson (jetzt Jenkins) Kohsuke Kawaguchi, der gerade veröffentlicht wurde (November 2013):
kohsuke / git-children-of :
Wie dieser Thread zeigt , gibt es in einem VCS, das auf dem Verlauf basiert, der durch eine DAG (Directed Acyclic Graph) dargestellt wird , nicht "ein Elternteil" oder "ein Kind".
Die Bestellung der Commits erfolgt nach "Topo-Order" oder "Date-Order" (siehe GitPro-Buch ).
Seit Git1.6.0 können Sie jedoch die untergeordneten Elemente eines Commits auflisten .
Hinweis: Bei übergeordneten Commits tritt das gleiche Problem auf. Das Suffix
^
eines Revisionsparameters bedeutet das erste übergeordnete Commit dieses Commit-Objekts.^<n>
Bedeutet die<n>
th Elternteil (dhrev^
ist äquivalent zurev^1
).Wenn Sie sich in einem Zweig befinden
foo
und "git merge bar
" ausgeben,foo
ist dies der erste Elternteil.Dh: Das erste übergeordnete Element ist der Zweig, in dem Sie sich beim Zusammenführen befanden, und das zweite ist das Festschreiben für den Zweig, in dem Sie zusammengeführt wurden.
quelle
git rev-list --children
sieht sicher so aus wie ich will, aber es DWIM nicht. Es scheint alle Eltern und ihre Kinder aufzulisten. Ich nehme an, ich kann sie alle auflisten und sie analysieren ... bleh, aber es ist etwas.git rev-list --children
ist nicht nur zum Auflisten von Kindern gedacht , sondern zum Auflisten von Eltern mit ihren Kindern ... Sie müssen immer analysieren.$ git children0of 9dd5932
fatal: No annotated tags can describe '71d7b5dd89d241072a0a078ff2c7dfec05d52e1f'.
However, there were unannotated tags: try --tags.
Welche Ausgabe erhalten Sie?git-children-of
ist, dass es git description verwendet , das versucht, den SHA als lesbar zu formatieren, was mit dem Fehler von @ TomHale fehlschlagen kann und solche Ergebnisse liefertv1.0.4-14-g2414721
, die verwirrend sind, wenn Sie einen SHA erwartet haben. Das Ersetzen durch ein einfachesecho
macht dies zu einem hervorragenden Werkzeug, danke!was ich gefunden habe ist
wo ich
commit1
als aktuelles Commit undcommit2
auf den aktuellen Kopf setze . Dies gibt mir eine Liste aller Commits zurück, die einen Pfad zwischencommit1
und bildencommit2
.Die letzte Zeile der Ausgabe ist das untergeordnete Element von commit1 (auf dem Pfad zu commit2).
quelle
| tail -1
, um das Kind zu bekommen.Ich weiß, was du meinst. Es ist frustrierend, reichlich Syntax zu haben, um zu früheren Commits zu gelangen, aber keine, um zu den nächsten zu gelangen. In einer komplexen Geschichte wird das Problem "Was ist das nächste Commit?" Ziemlich schwierig, aber beim komplexen Zusammenführen tritt dieselbe Härte auch bei "vorherigen" Commits auf. Im einfachen Fall wäre es in einem einzelnen Zweig mit einer linearen Historie (auch nur lokal für eine begrenzte Anzahl von Commits) schön und sinnvoll, vorwärts und rückwärts zu gehen.
Das eigentliche Problem dabei ist jedoch, dass die untergeordneten Commits nicht referenziert werden, sondern nur eine rückwärts verknüpfte Liste. Um das untergeordnete Commit zu finden, ist eine Suche erforderlich, die nicht allzu schlecht ist, aber wahrscheinlich nicht etwas, das Git in die Refspec-Logik aufnehmen möchte.
Auf jeden Fall bin ich auf diese Frage gestoßen, weil ich einfach einen Schritt nach dem anderen in der Geschichte vorwärts gehen möchte, Tests mache, und manchmal muss man vorwärts und nicht rückwärts gehen. Nun, mit ein paar weiteren Gedanken kam ich auf diese Lösung:
Wählen Sie ein Commit aus, bevor Sie sich gerade befinden. Dies könnte wahrscheinlich ein Zweigkopf sein. Wenn Sie sich in Zweig ~ 10 befinden, dann "Git Checkout-Zweig ~ 9", dann "Git Checkout-Zweig ~ 8", um den nächsten zu erhalten, dann "Git Checkout-Zweig ~ 7" und so weiter.
Das Dekrementieren der Nummer sollte in einem Skript wirklich einfach sein, wenn Sie es brauchen. Viel einfacher als das Parsen der Git-Rev-Liste.
quelle
BRANCH=master; git co $BRANCH~$[ $(git rev-list HEAD..$BRANCH | wc -l) - 1 ]
" Sie müssen auf einen Ast zugehen, daran führt kein Weg vorbei.Zwei praktische Antworten:
Ein Kind
Basierend auf @ Michaels Antwort habe ich den
child
Alias in meinem gehackt.gitconfig
.Es funktioniert im Standardfall wie erwartet und ist außerdem vielseitig einsetzbar.
Standardmäßig wird das untergeordnete Element von HEAD angegeben (sofern kein anderes Commit-ish-Argument angegeben wird), indem der Abstammung ein Schritt in Richtung der Spitze des aktuellen Zweigs gefolgt wird (es sei denn, ein anderes Commit-ish wird als zweites Argument angegeben).
Verwenden Sie
%h
anstelle von%H
wenn Sie das kurze Hash-Formular möchten.Mehrere Kinder
Mit einem abgetrennten KOPF (es gibt keinen Zweig) oder um alle Kinder unabhängig von Zweigen zu bekommen:
Ändern Sie das
$1
in$*
, um alle zu drucken.Sie können auch
--all
zu einem Commit wechseln , um nur die untergeordneten Elemente anzuzeigen, die Vorfahren dieses Commits sind. Mit anderen Worten, um nur die untergeordneten Elemente "in Richtung" des angegebenen Commits anzuzeigen. Dies kann Ihnen helfen, die Ausgabe von vielen Kindern auf nur eines zu beschränken.quelle
Es gibt kein eindeutiges "nächstes Commit". Da der Verlauf in Git eine DAG und keine Zeile ist, können viele Commits ein gemeinsames übergeordnetes Element (Zweige) und Commits mehr als ein übergeordnetes Element (Zusammenführungen) haben.
Wenn Sie an einen bestimmten Zweig denken, können Sie in dessen Protokoll nachsehen, in welchem Commit der aktuelle Zweig als übergeordneter aufgeführt ist.
quelle
<rev>^
ist "übergeordnetes Commit" ("erstes übergeordnetes Element" für Zusammenführungs-Commits).Ich habe viele verschiedene Lösungen ausprobiert und keine hat für mich funktioniert. Musste mir meine einfallen lassen.
Finde das nächste Commit
Vorheriges Commit finden
quelle
Wenn Sie kein bestimmtes "Ziel" -Commit im Auge haben, sondern untergeordnete Commits anzeigen möchten, die sich möglicherweise in einem Zweig befinden, können Sie diesen Befehl verwenden:
Wenn Sie alle Kinder und Enkelkinder sehen möchten , müssen Sie wie folgt
rev-list --children
rekursiv verwenden:(Die Version, die nur Enkelkinder gibt, würde eine komplexere
sed
und / oder verwendencut
.)Schließlich können Sie dies in einen
log --graph
Befehl einspeisen, um die Baumstruktur wie folgt anzuzeigen:Hinweis : Bei den obigen Befehlen wird davon ausgegangen, dass Sie die Shell-Variable
${COMMIT}
auf eine Referenz (branch, tag, sha1) des Commits festgelegt haben, dessen untergeordnete Elemente Sie interessieren.quelle
${COMMIT}
besteht es nicht, aber Sie könnten$(git rev-parse HEAD)
stattdessen verwenden${COMMIT}
.(Dies begann als Antwort auf eine doppelte Frage. Ich habe ein wenig Licht bearbeitet, um sie zu bereinigen.)
Alle internen Pfeile von Git sind einseitig und zeigen nach hinten. Es gibt daher keine kurze bequeme Syntax für das Vorwärtsbewegen: Es ist einfach nicht möglich.
Es ist möglich, sich "gegen die Pfeile zu bewegen", aber die Vorgehensweise ist überraschend, wenn Sie es noch nicht gesehen haben und danach offensichtlich. Nehmen wir an, wir haben:
Mit
middle~2
folgt die Pfeile zweimal vonC
zurück nachA
. Wie bewegen wir uns vonC
nachD
? Die Antwort ist: Wir beginnen beiE
, den Namen mitlast
, und die Arbeit nach hinten , bis wir bekommenmiddle
, das Aufzeichnen der Punkte , die wir auf dem Weg besuchen . Dann bewegen wir uns einfach so weit wie wir wollen in die Richtunglast
: einen Schritt nachD
oder zwei nachE
.Dies ist besonders wichtig, wenn wir Niederlassungen haben:
Welches Commit ist einen Schritt später
C
? Es gibt keine richtige Antwort, bis Sie der Frage hinzufügen: in Richtung feature___ (füllen Sie die Lücke aus ).Um die Commits zwischen
C
(ohneC
) sich selbst und beispielsweise aufzuzählenG
, verwenden wir:Dies
--topo-order
stellt sicher, dass die Commits auch bei komplexen Verzweigungen und Zusammenführungen in topologisch sortierter Reihenfolge ausgeführt werden. Dies ist nur erforderlich, wenn die Kette nicht linear ist. Die--ancestry-path
Einschränkung bedeutet, dass wir, wenn wir rückwärts von arbeitenfeature2
, nur Commits auflisten, die CommitC
als einen ihrer eigenen Vorfahren haben. Das heißt, wenn das Diagramm - oder der relevante Teil davon - tatsächlich so aussieht:eine einfache Anfrage des Formulars
feature2..master
aufzählt CommitsJ
,G
undI
, undF
undH
in einer bestimmten Reihenfolge. Mit--ancestry-path
schlagen wir ausH
undI
: Sie sind keine Nachkommen vonC
, nur vonA
. Mit stellen--topo-order
wir sicher, dass die tatsächliche AufzählungsreihenfolgeJ
dannG
, dann istF
.Der
git rev-list
Befehl verschüttet diese Hash-IDs in seiner Standardausgabe, eine pro Zeile. Um einen Schritt vorwärts in Richtung zu gehenfeature2
, wollen wir nur die letzte Zeile.Das Hinzufügen ist möglich (und verlockend und kann nützlich sein),
--reverse
sodassgit rev-list
die Commits nach dem Generieren in umgekehrter Reihenfolge gedruckt werden. Dies funktioniert, aber wenn Sie es in einer Pipeline wie dieser verwenden:Um nur das "nächste Commit in Richtung von id2" zu erhalten, und es gibt eine sehr lange Liste von Commits, kann der
git rev-list
Befehl eine fehlerhafte Pipe bekommen, wenn er versucht zu schreiben,head
die seine Eingabe nicht mehr gelesen und beendet hat. Da Rohrbruchfehler normalerweise von der Shell ignoriert werden, funktioniert dies meistens. Stellen Sie einfach sicher, dass sie bei Ihrer Verwendung ignoriert werden .Es ist auch verlockend,
-n 1
dengit rev-list
Befehl zusammen mit hinzuzufügen--reverse
. Tu es nicht! Dies führt dazu,git rev-list
dass Sie nach einem Schritt zurück anhalten und dann die Liste der besuchten Commits (mit einem Eintrag) umkehren. Das produziert also<id2>
jedes Mal.Wichtige Randnotiz
Beachten Sie, dass bei "Diamant" - oder "Benzolring" -Graphenfragmente:
Wenn Sie ein Commit "vorwärts" von in
H
Richtung bewegen,last
erhalten Sie entwederI
oderK
. Daran können Sie nichts ändern: Beide Commits sind einen Schritt vorwärts! Wenn Sie dann mit dem resultierenden Commit beginnen und einen weiteren Schritt ausführen, werden Sie jetzt auf den Pfad festgelegt, auf dem Sie begonnen haben.Die Heilung dafür besteht darin, zu vermeiden, dass Sie sich Schritt für Schritt bewegen und in pfadabhängige Ketten geraten. Wenn Sie stattdessen vorhaben, eine gesamte Ahnenpfadkette zu besuchen, bevor Sie etwas anderes tun, erstellen Sie eine vollständige Liste aller Commits in der Kette:
Besuchen Sie dann jedes Commit in dieser Liste nacheinander, und Sie erhalten die gesamte Kette. Das
--topo-order
wird sicherstellen , dass Sie treffenI
-und-J
in dieser Reihenfolge, undK
-und-L
in dieser Reihenfolge (obwohl es keine einfache Möglichkeit , vorherzusagen , ob Sie vor oder nach dem KL Paar das IJ Paar werde tun).quelle
Ich habe diesen Alias in
~/.gitconfig
quelle
f()
? Und es muss seinhead -1
, das erste Kind zu sein, sonst meldet dies einfach den KOPF.f()
. Ja,head -1
ist eine mutige Vermutung.nextref = "!f() { git log --reverse --ancestry-path --pretty=%H $1..HEAD | head -${2:-1} | tail -1; }; f"
So können Sie optional auswählen, wie weit Sie voraus sindIch habe es geschafft, das nächste Kind folgendermaßen zu finden:
quelle
Wenn sich die untergeordneten Commits alle in einem Zweig befinden, können Sie verwenden
gitk --all commit^..
, wobei "Commit" das Commit identifiziert. Wenn der abgekürzte SHA-1 des Commits beispielsweise c6661c5 lautet, geben Sie Folgendes eingitk --all c6661c5^..
Sie müssen wahrscheinlich den vollständigen SHA-1 in die Zelle "SHA1 ID:" von gitk eingeben. Sie benötigen den vollständigen SHA-1, der für dieses Beispiel über erhältlich ist
git rev-parse c6661c5
Alternativ
git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d'
wird eine Zeile erstellt, die alle untergeordneten Elemente dieses Commits enthält, vermutlich unabhängig davon, ob ein Zweig beteiligt ist oder nicht.quelle
Jedes Commit speichert einen Zeiger auf sein übergeordnetes Element (Eltern, im Falle eines Zusammenführungs-Commits (Standard)).
Es gibt also keine Möglichkeit, auf ein untergeordnetes Commit (falls vorhanden) des Elternteils hinzuweisen.
quelle
Dieser Beitrag ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) zeigt einen ordentlichen Weg, wenn Sie dies tun, wenn Sie können am Ende Ihres Commit-Stacks ein genau definiertes Tag erstellen. Im Wesentlichen,
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
wo "Demo-Ende" das letzte Tag ist.quelle
Bei vorhandenen Antworten wird davon ausgegangen, dass Sie einen Zweig haben, der das gesuchte Commit enthält.
In meinem Fall war das von mir gesuchte Commit nicht aktiviert
git rev-list --all
da dies in keinem Zweig enthalten war.Am Ende habe ich durchgesehen
gitk --reflog
manuell .Wenn Sie Ihr Commit nicht einmal im Reflog finden können, versuchen Sie Folgendes:
git fsck --full
baumelnde Commits (dh nicht in einem Zweig) aufzulisten, odergit fsck --lost-found
Refs zu machen, die auf baumelnde Commits hinweisen, Techniken in den anderen Antworten anzuwenden.quelle