Finde heraus, aus welchem ​​Zweig ein Git-Commit stammt

Gibt es eine Möglichkeit herauszufinden, aus welchem ​​Zweig ein Commit kommt, wenn man sha1 benutzt?

Bonuspunkte, wenn Sie mir sagen können, wie Sie dies mit Ruby Grit erreichen können.

   

Während Dav richtig ist, dass die Informationen nicht direkt gespeichert werden, heißt das nicht, dass Sie es nie herausfinden können. Hier sind ein paar Dinge, die Sie tun können.

Finde die Zweige, auf denen das Commit läuft

git branch --contains  

Dies wird Ihnen alle Zweige mitteilen, die das angegebene Commit in ihrer Geschichte haben. Offensichtlich ist dies weniger nützlich, wenn die Commits bereits zusammengeführt wurden.

Durchsuchen Sie die Reflogs

Wenn Sie in dem Repository arbeiten, in dem das Commit durchgeführt wurde, können Sie die Reflogs nach der Zeile für dieses Commit durchsuchen. Reflogs, die älter als 90 Tage sind, werden von git-gc gelöscht. Wenn das Commit also zu alt ist, werden Sie es nicht finden. Das heißt, Sie können dies tun:

 git reflog show --all | grep a871742 

finden Sie commit a871742. Die Ausgabe sollte etwa so aussehen:

 a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite 

Angeben, dass das Commit auf der Verzweigung “Completion” erfolgte. Die Standardausgabe zeigt abgekürzte Commit-Hashes. Achten Sie also darauf, nicht nach dem vollständigen Hash zu suchen, sonst finden Sie nichts.

git reflog show ist eigentlich nur ein Alias ​​für git log -g --abbrev-commit --pretty=oneline . Wenn Sie also mit dem Ausgabeformat git log -g --abbrev-commit --pretty=oneline , um verschiedene Dinge für grep verfügbar zu machen, ist das Ihr Ausgangspunkt!

Wenn Sie nicht in dem Repository arbeiten, in dem das Commit durchgeführt wurde, sollten Sie in diesem Fall die Reflogs überprüfen und herausfinden, wann das Commit zum ersten Mal in Ihrem Repo eingeführt wurde. Mit etwas Glück holten Sie den Zweig, an den sie gebunden war. Dies ist etwas komplexer, da Sie den Commit Tree und die Reflogs nicht gleichzeitig ausführen können. Sie sollten die Reflog-Ausgabe analysieren und jeden Hash überprüfen, um festzustellen, ob er die gewünschte Festschreibung enthält oder nicht.

Suchen Sie einen nachfolgenden Zusammenführungs-Commit

Dies ist Workflow-abhängig, aber bei guten Workflows werden Commits in Entwicklungszweigen gemacht, die dann zusammengeführt werden. Sie könnten dies tun:

 git log --merges .. 

um Zusammenführungs-Commits zu sehen, die das angegebene Commit als einen Vorfahren haben. (Wenn der Commit nur einmal zusammengeführt wurde, sollte der erste der Merge sein, nach dem Sie suchen; andernfalls müssen Sie einige davon untersuchen, nehme ich an.) Die Nachricht zum Zusammenführen von Commits sollte den Zweignamen enthalten, der zusammengeführt wurde.

Wenn Sie sich darauf verlassen können, möchten Sie vielleicht die Option --no-ff um git merge zu verschicken, um die Erstellung von Merge-Commits auch im Schnellvorlauf zu erzwingen. (Werden Sie jedoch nicht zu eifrig, das könnte verschleiern, wenn es übernutzt wird.) VonCs Antwort auf eine verwandte Frage hilft hilfreich, dieses Thema zu behandeln.

Update Dezember 2013:

sschubberth Kommentare

git-what-branch (Perl-Skript, siehe unten) scheint nicht mehr gepflegt zu werden.
git-when-merged ist eine in Python geschriebene Alternative, die sehr gut für mich funktioniert.

Es basiert auf ” Find merge commit, die ein bestimmtes Commit enthalten “.

 git when-merged [OPTIONS] COMMIT [BRANCH...] 

Finden Sie, wann ein Commit in einen oder mehrere Zweige zusammengeführt wurde.
Suchen Sie das Zusammenführungs-Commit, das COMMIT in die angegebenen BRANCH (es) brachte.

BRANCH spezifisch nach dem ältesten COMMIT BRANCH in der First-Parent-Historie von BRANCH , das das COMMIT als Vorfahr enthält.


Ursprüngliche Antwort September 2010:

Sebastien Douche hat gerade gezwitschert (16 Minuten vor dieser SO Antwort):

git-what-branch : Entdecke, in welchem ​​Zweig sich ein Commit befindet oder wie er in einen benannten Zweig gelangt ist

Dies ist ein Perl-Skript von Seth Robertson , das sehr interessant erscheint:

ZUSAMMENFASSUNG

 git-what-branch [--allref] [--all] [--topo-order | --date-order ] [--quiet] [--reference-branch=branchname] [--reference=reference] ... 

ÜBERBLICK

Sagen Sie uns (standardmäßig) den frühesten kausalen Pfad von Commits und Merges, damit das angeforderte Commit in einen benannten Zweig gelangt.
Wenn ein Commit direkt in einem benannten Zweig ausgeführt wurde, ist dies offensichtlich der früheste Pfad.

Unter frühestem --topo-order verstehen wir den Pfad, der frühestens nach Commit-Zeit in einen benannten Zweig --topo-order (es sei denn – --topo-order ist angegeben).

PERFORMANCE

Wenn viele Verzweigungen (z. B. Hunderte) das Commit enthalten, kann das System eine lange Zeit benötigen (für ein bestimmtes Commit in der Linux-Struktur dauerte es 8 Sekunden, um einen Zweig zu erkunden, aber es gab über 200 Kandidatenzweige), um den Pfad aufzuspüren zu jedem Commit.
Die Auswahl eines bestimmten --reference-branch --reference tag , das untersucht werden soll, ist --reference-branch --reference tag schneller (wenn Sie Hunderte von Kandidatenzweigen haben).

Beispiele

  # git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path: v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005) v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005) v2.6.12-rc3-461-g84e48b6 is on master v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n [...] 

Dieses Programm berücksichtigt nicht die Effekte des Rosinenpickens des Commit of Interest, nur Merge-Operationen.

Zum Beispiel, dass c0118fa commit von redesign_interactions

 * ccfd449 (HEAD -> develop) Require to return undef if no digits found * 93dd5ff Merge pull request #4 from KES777/clean_api |\ | * 39d82d1 Fix tc0118faests for debugging debugger internals | * ed67179 Move &push_frame out of core | * 2fd84b5 Do not lose info about call point | * 3ab09a2 Improve debugger output: Show info about emitted events | * a435005 Merge branch 'redesign_interactions' into clean_api | |\ | | * a06cc29 Code comments | | * d5d6266 Remove copy/paste code | | * c0118fa Allow command to choose how continue interaction | | * 19cb534 Emit &interact event 

Du solltest rennen:

 git log c0118fa..HEAD --ancestry-path --merges 

Und scrollen Sie nach unten, um den letzten Merge- Commit zu finden. Welches ist:

 commit a435005445a6752dfe788b8d994e155b3cd9778f Merge: 0953cac a06cc29 Author: Eugen Konkov Date: Sat Oct 1 00:54:18 2016 +0300 Merge branch 'redesign_interactions' into clean_api 

UPD
Oder nur einen Befehl:

 git log 56a44a5..HEAD --ancestry-path --merges --oneline --color | tail -n 1 

Dieser einfache Befehl funktioniert wie ein Zauber:

git name-rev

Zum Beispiel (wobei test-branch der Name der Verzweigung ist):

 git name-rev 651ad3a 251ad3a remotes/origin/test-branch 

Auch das funktioniert für komplexe Szenarien wie: origin/branchA/ /branchB /commit /commit

Hier gibt git name-rev commit Wert von git name-rev commit zurück

git branch --contains ist der offensichtlichste “Porzellan” Befehl, dies zu tun. Wenn Sie etwas ähnliches mit nur “plumbing” -Befehlen machen wollen:

 COMMIT=$(git rev-parse ) # expands hash if needed for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do if $(git rev-list $BRANCH | fgrep -q $COMMIT); then echo $BRANCH fi done 

(Crosspost von dieser SO Antwort )

Die Option des armen Mannes besteht darin, das Tool tig 1 auf HEAD , nach dem Commit zu suchen und dann visuell die Linie von diesem Commit-Backup bis zu einem Merge-Commit zu verfolgen. Die Standardnachricht zum Zusammenführen sollte angeben, welcher Zweig mit wo zusammengeführt wird 🙂

1 Tig ist eine ncurses-basierte Textmodus-Schnittstelle für Git. Es funktioniert hauptsächlich als ein Git-Repository-Browser, kann aber auch bei der Bereitstellung von Änderungen für das Festschreiben auf Chunk-Ebene helfen und als Pager für die Ausgabe von verschiedenen Git-Befehlen dienen.

Als Experiment habe ich einen Post-Commit-Hook erstellt, der Informationen über den aktuell ausgecheckten Zweig in den Commit-Metadaten speichert. Ich habe auch etwas geändert, um diese Information zu zeigen.

Sie können es hier überprüfen: https://github.com/pajp/branch-info-commits

Wenn das OP versucht, den Verlauf zu ermitteln, der von einem Zweig durchlaufen wurde, als ein bestimmter Commit erstellt wurde (“Finde heraus, aus welchem ​​Zweig ein Commit stammt, gegebenes sha1”), dann gibt es ohne den Reflog keine Datensätze in der Git-Objektdatenbank zeigt an, welcher benannte Zweig an welchen Commitverlauf gebunden ist.

(Ich habe dies als Antwort auf einen Kommentar gepostet)

Hoffentlich illustriert dieses Skript meinen Punkt:

 rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1 git init; git config user.name n; git config user.email e@x.io git commit -m"empty" --allow-empty; git branch -m b1; git branch b2 git checkout b1; touch f1; git add f1; git commit -m"Add f1" git checkout b2; touch f2; git add f2; git commit -m"Add f2" git merge -m"merge branches" b1; git checkout b1; git merge b2 git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2 set -x; cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2; cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2; 

Die Ausgabe zeigt, dass es keine Möglichkeit gibt zu wissen, ob das Commit mit ‘Add f1’ von dem Zweig b1 oder b2 von dem entfernten Klon / tmp / r2 kam

(letzte Zeilen der Ausgabe hier)

 + cd /tmp/r1 + git log --oneline --graph --decorate * f0c707d (HEAD, b2, b1) merge branches |\ | * 086c9ce Add f1 * | 80c10e5 Add f2 |/ * 18feb84 empty + git reflog b1 f0c707d b1@{0}: merge b2: Fast-forward 086c9ce b1@{1}: commit: Add f1 18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1 18feb84 b1@{3}: commit (initial): empty + git reflog b2 f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy. 80c10e5 b2@{1}: commit: Add f2 18feb84 b2@{2}: branch: Created from b1 + cd /tmp/r2 + git log --oneline --graph --decorate * f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches |\ | * 086c9ce Add f1 * | 80c10e5 Add f2 |/ * 18feb84 empty + git reflog b1 f0c707d b1@{0}: clone: from /tmp/r1 + git reflog b2 f0c707d b2@{0}: fetch origin b2:b2: storing head 

Um eine lokale Niederlassung zu finden

 grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g' 

Um entfernte Zweigstelle zu finden

 grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g' 

Abgesehen von der Suche durch den gesamten Baum, bis Sie einen passenden Hash finden, nein.