Gibt es eine Möglichkeit herauszufinden, von welchem Zweig ein Commit aufgrund seines SHA-1- Hashwerts stammt?
Bonuspunkte, wenn Sie mir sagen können, wie dies mit Ruby Grit erreicht werden kann.
Gibt es eine Möglichkeit herauszufinden, von welchem Zweig ein Commit aufgrund seines SHA-1- Hashwerts stammt?
Bonuspunkte, wenn Sie mir sagen können, wie dies mit Ruby Grit erreicht werden kann.
Antworten:
Während Dav richtig ist, dass die Informationen nicht direkt gespeichert sind, heißt das nicht, dass Sie es nie herausfinden können. Hier sind einige Dinge, die Sie tun können.
git branch -a --contains <commit>
Hier erfahren Sie alle Zweige, die in ihrer Geschichte das angegebene Commit haben. Dies ist natürlich weniger nützlich, wenn das Commit bereits zusammengeführt wurde.
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 beschnitten. 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
Commit finden a871742. Beachten Sie, dass Sie die abgekürzten 7 ersten Ziffern des Commits verwenden MÜSSEN. Die Ausgabe sollte ungefähr so aussehen:
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
Dies zeigt an, dass das Commit für den Zweig "Abschluss" vorgenommen wurde. In der Standardausgabe werden abgekürzte Commit-Hashes angezeigt. Suchen Sie daher nicht nach dem vollständigen Hash, da Sie sonst nichts finden.
git reflog show
ist eigentlich nur ein Alias für git log -g --abbrev-commit --pretty=oneline
. Wenn Sie also mit dem Ausgabeformat herumspielen möchten, um verschiedene Dinge zur Verfügung zu stellen, nach denen Sie suchen können, ist dies Ihr Ausgangspunkt!
Wenn Sie nicht in dem Repository arbeiten, in dem das Commit durchgeführt wurde, können Sie in diesem Fall am besten die Reflogs untersuchen und feststellen, wann das Commit zum ersten Mal in Ihr Repository eingeführt wurde. Mit etwas Glück haben Sie den Zweig geholt, für den er bestimmt war. Dies ist etwas komplexer, da Sie nicht gleichzeitig den Commit-Baum und die Reflogs durchlaufen können. Sie möchten die Reflog-Ausgabe analysieren und jeden Hash untersuchen, um festzustellen, ob er das gewünschte Commit enthält oder nicht.
Dies ist vom Workflow abhängig. Bei guten Workflows werden jedoch Commits für Entwicklungszweige vorgenommen, die dann zusammengeführt werden. Sie können dies tun:
git log --merges <commit>..
um Merge-Commits zu sehen, die das angegebene Commit als Vorfahren haben. (Wenn das Commit nur einmal zusammengeführt wurde, sollte das erste das Zusammenführen sein, nach dem Sie suchen. Andernfalls müssen Sie vermutlich einige untersuchen.) Die Commit-Nachricht zum Zusammenführen sollte den zusammengeführten Zweignamen enthalten.
Wenn Sie sich darauf verlassen möchten, können Sie die --no-ff
Option verwenden, git merge
um die Erstellung von Zusammenführungs-Commits auch im Schnellvorlauf zu erzwingen. ( Seien Sie jedoch nicht zu eifrig. Das könnte bei Überbeanspruchung verschleiern.) VonCs Antwort auf eine verwandte Frage geht hilfreich auf dieses Thema ein.
git describe
aus, da (mit Anmerkungen versehene) Tags als wichtiger als Zweige angesehen werden können.
--no-ff
Option sicherstellen, dass immer ein Zusammenführungs-Commit vorhanden ist, sodass Sie den Pfad eines bestimmten Commits immer verfolgen können, wenn es zum Master zusammengeführt wird.
-a
Flag zum ersten Befehl hinzu, z. B.git branch -a --contains <commit>
-r
.
merge --no-ff
, um den Filialnamen beim Zusammenführen zuverlässig aufzuzeichnen. Stellen Sie sich ansonsten Filialnamen als temporäre Kurzbezeichnungen vor und schreiben Sie Beschreibungen als permanente fest. "Mit welchem Kurznamen haben wir uns während der Entwicklung darauf bezogen?" sollte wirklich keine so wichtige Frage sein wie "Was macht dieses Commit?"
Dieser einfache Befehl funktioniert wie ein Zauber:
git name-rev <SHA>
Zum Beispiel (wobei test-branch der Name des Zweigs ist):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
Auch dies funktioniert für komplexe Szenarien wie:
origin/branchA/
/branchB
/commit<SHA1>
/commit<SHA2>
Hier git name-rev commit<SHA2>
gibt branchB .
git name-rev --name-only <SHA>
es nützlicher, nur den Filialnamen zu erhalten. Meine Frage ... Kann es unter keinen Umständen mehr als einen Zweig zurückgeben?
Update Dezember 2013:
git-what-branch
(Perl-Skript, siehe unten) scheint nicht mehr gepflegt zu sein.git-when-merged
ist eine in Python geschriebene Alternative, die für mich sehr gut funktioniert.
Es basiert auf " Find Merge Commit, das ein bestimmtes Commit enthält ".
git when-merged [OPTIONS] COMMIT [BRANCH...]
Finden Sie heraus, wann ein Commit in einem oder mehreren Zweigen zusammengeführt wurde.
Suchen Sie das Zusammenführungs-Commit, dasCOMMIT
in die angegebenen BRANCHEN eingeführt wurde.Suchen Sie insbesondere nach dem ältesten Commit im Verlauf des ersten übergeordneten Elements
BRANCH
, das dasCOMMIT
als Vorfahr enthält.
Ursprüngliche Antwort September 2010:
Sebastien Douche hat gerade gezwitschert (16 Minuten vor dieser SO-Antwort):
git-what-branch : Ermitteln Sie, in welchem Zweig sich ein Commit befindet oder wie er zu einem 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]
<commit-hash/tag>...
ÜBERBLICK
Teilen Sie uns (standardmäßig) den frühesten kausalen Pfad von Commits und Zusammenführungen mit, damit das angeforderte Commit in einen benannten Zweig gelangt. Wenn ein Commit direkt für einen benannten Zweig durchgeführt wurde, ist dies offensichtlich der früheste Pfad.
Mit dem frühesten kausalen Pfad meinen wir den Pfad, der am frühesten zu einem benannten Zweig verschmolzen ist, mit Festschreibungszeit (sofern
--topo-order
nicht anders angegeben).PERFORMANCE
Wenn viele Zweige (z. B. Hunderte) das Commit enthalten, kann es lange dauern, bis das System den Pfad gefunden hat (für ein bestimmtes Commit im Linux-Baum dauerte es 8 Sekunden, um einen Zweig zu untersuchen, aber es gab über 200 Kandidatenzweige) zu jedem Commit.
Die Auswahl einer--reference-branch --reference tag
zu untersuchenden Person ist hunderte Male 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 Auswirkungen der Auswahl des interessierenden Commits, sondern nur Zusammenführungsvorgänge.
git-what-branch
scheint nicht mehr gepflegt zu sein. Git-When-Merged ist eine in Python geschriebene Alternative, die für mich sehr gut funktioniert.
Um dieses c0118fa
Commit zu finden, kam es beispielsweise 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
Scrollen Sie nach unten, um das Commit für die letzte Zusammenführung 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
Aktualisieren
Oder nur ein Befehl:
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
git merge -m"Any String Here"
wird die Quell- und Zielbranchen Informationen verschleiern.
Merge: f6b70fa d58bdcb
. Sie können Ihr Merge-Commit so benennen, wie Sie es möchten. Ich werde keine Materie haben
git branch --contains <ref>
ist der offensichtlichste "Porzellan" -Befehl, um dies zu tun. Wenn Sie etwas Ähnliches nur mit "Sanitär" -Befehlen tun möchten:
COMMIT=$(git rev-parse <ref>) # 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 )
khichar.anil behandelte das meiste davon in seiner Antwort.
Ich füge nur das Flag hinzu, mit dem die Tags aus der Liste der Revisionsnamen entfernt werden. Dies gibt uns:
git name-rev --name-only --exclude=tags/* $SHA
Die Option eines armen Mannes besteht darin, das Tool tig
1 zu verwenden HEAD
, nach dem Commit zu suchen und dann der Linie von diesem Commit visuell zu folgen, bis ein Zusammenführungs-Commit angezeigt wird. Die Standard-Zusammenführungsnachricht sollte angeben, welcher Zweig wo zusammengeführt wird :)
1 Tig ist eine ncurses-basierte Textmodus-Oberfläche für Git. Es fungiert hauptsächlich als Git-Repository-Browser, kann aber auch beim Staging von Änderungen für das Festschreiben auf Chunk-Ebene helfen und als Pager für die Ausgabe verschiedener Git-Befehle fungieren.
Als Experiment habe ich einen Post-Commit-Hook erstellt, der Informationen über den aktuell ausgecheckten Zweig in den Commit-Metadaten speichert. Ich habe auch gitk leicht modifiziert, um diese Informationen anzuzeigen.
Sie können es hier überprüfen: https://github.com/pajp/branch-info-commits
Ich beschäftige mich mit demselben Problem ( Jenkins Multibranch-Pipeline) - ich habe nur Commit-Informationen und versuche, einen Zweigstellennamen zu finden, von dem dieses Commit ursprünglich stammt. Es muss für Remote-Zweige funktionieren, lokale Kopien sind nicht verfügbar.
Damit arbeite ich:
git rev-parse HEAD | xargs git name-rev
Optional können Sie die Ausgabe entfernen:
git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
Ich denke, jemand sollte mit dem gleichen Problem konfrontiert sein, das den Zweig nicht herausfinden kann, obwohl er tatsächlich in einem Zweig existiert.
Du solltest besser zuerst alles ziehen:
git pull --all
Führen Sie dann die Zweigsuche durch:
git name-rev <SHA>
oder:
git branch --contains <SHA>
Wenn das OP versucht, den Verlauf zu ermitteln, der von einem Zweig beim Erstellen eines bestimmten Commits durchlaufen wurde ("Finden Sie heraus, von welchem Zweig ein Commit aufgrund seines SHA-1-Hashwerts stammt"), gibt es ohne das Reflog keine Datensätze in der Git-Objektdatenbank , die zeigen, welcher benannte Zweig an welchen Commit-Verlauf gebunden war.
(Ich habe dies als Antwort auf einen Kommentar gepostet.)
Hoffentlich veranschaulicht dieses Skript meinen Standpunkt:
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' vom Zweig b1 oder b2 vom Remote-Klon / tmp / r2 stammt.
(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
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
und git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
Befehle für beide Fälle?
$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
welche Ausbeuten 376142d merge branches
und $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
welche Ausbeuten 376142d merge branches
- welche die Zusammenfassung des Zusammenführungs-Commits zeigen, die (wie ich behauptet habe) beim Erstellen der Zusammenführung überschrieben werden kann, wodurch möglicherweise der Verzweigungsverlauf der Zusammenführung verschleiert wird.
Verwenden Sie Folgendes, wenn Sie sich für den Status des Shell-Exits interessieren:
branch-current
- Name der aktuellen Filialebranch-names
- saubere Filialnamen (einer pro Zeile)branch-name
- Stellen Sie sicher, dass nur ein Zweig zurückgegeben wird branch-names
Beide branch-name
und branch-names
akzeptieren ein Commit als Argument und standardmäßig, HEAD
wenn keines angegeben ist.
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
% git branch-name eae13ea
master
% echo $?
0
0
.% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
.Aufgrund des Exit-Status können diese sicher aufgebaut werden. So verwenden Sie beispielsweise die zum Abrufen verwendete Fernbedienung:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
So finden Sie die lokale Niederlassung:
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
So finden Sie den Remote-Zweig:
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'
Abgesehen davon, dass Sie den gesamten Baum durchsuchen, bis Sie einen passenden Hash gefunden haben, nein.