894 Stimmen

Herausfinden, aus welchem Zweig eine Git-Übertragung stammt

Gibt es eine Möglichkeit, herauszufinden, aus welchem Zweig ein Commit stammt, wenn man seine SHA-1 Hash-Wert?

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

19 Stimmen

Die folgenden Methoden sind pragmatische, nützliche und funktionierende Wege, um ableiten a Wahrscheinlich Antwort, aber beachten Sie, dass in Git die Frage selbst ein Missverständnis ist: Commits kommen nicht aus Zweigen. Zweige kommen und gehen, sie bewegen sich, nur Commits repräsentieren die wirkliche Repo-Historie. Das soll aber nicht heißen, dass die unten genannten Lösungen schlecht sind. Nur wissen keine von ihnen gibt eine vollständig vertrauenswürdige Antwort, was in Git absichtlich nicht möglich ist. (Ein einfacher Fall sind gelöschte Verzweigungen: Ich verzweige, ich übertrage zweimal, ich führe in eine andere Verzweigung zusammen, ich lösche die erste Verzweigung. Woher "kommt" die Übergabe?

2 Stimmen

Ich habe einen Fall, in dem ich explizit eine Tiefe 1 flachen Klon aus einem Tag ziehen. Es ist billig und einfach und effizient ... und bis jetzt tat alles, was ich wollte schön. Jetzt, wo ich wissen möchte, auf welchem Zweig das Tag war, bin ich aufgeschmissen, zumindest für dieses Detail. Man kann nicht immer nach Hause gehen, lol

2voto

qneill Punkte 1565

Wenn der Auftraggeber versucht, die Geschichte die von einem Zweig durchquert wurde, als ein bestimmter Commit erstellt wurde ("herausfinden, aus welchem Zweig ein Commit kommt, wenn man seinen SHA-1-Hash-Wert betrachtet"), dann gibt es ohne das Reflog keine alle Einträge in der Git-Objektdatenbank die zeigt, welcher benannte Zweig an welche Commit-Historie gebunden war.

(Ich habe dies als Antwort auf einen Kommentar gepostet.)

Ich hoffe, dieses Skript veranschaulicht 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, herauszufinden, ob der Commit mit 'Add f1' vom Zweig b1 oder b2 aus dem entfernten 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

0 Stimmen

Und wie lautet die Ausgabe für git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1 y git log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1 Befehle für beide Fälle?

0 Stimmen

Die SHAs ändern sich natürlich jedes Mal, wenn die Befehle ausgeführt werden; um Ihre Befehle neu zu schreiben, habe ich KOPF^1 y KOPF^2 auf einen neuen Anlauf. Die Befehle und Ausgaben sind: $ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1 was zu folgenden Ergebnissen führt 376142d merge branches y $ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1 was zu folgenden Ergebnissen führt 376142d merge branches -- die die Zusammenfassung der Zusammenführungsübergabe anzeigt, die (wie ich behauptet habe) überschrieben werden kann, wenn die Zusammenführung erstellt wird, wodurch die Zweiggeschichte der Zusammenführung möglicherweise verschleiert wird.

1voto

Tom Hale Punkte 32065

TL;DR:

Verwenden Sie die unten stehenden Angaben, wenn Sie sich für den Shell-Exit-Status interessieren:

  • branch-current - den Namen der aktuellen Zweigstelle
  • branch-names - saubere Zweignamen (einer pro Zeile)
  • branch-name - Stellen Sie sicher, dass nur eine Verzweigung von branch-names

Beide branch-name y branch-names akzeptieren eine Übergabe als Argument und sind standardmäßig auf HEAD wenn keine angegeben ist.


Bei der Skripterstellung nützliche Aliase

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\" #"

Commit nur von einem Zweig aus erreichbar

% git branch-name eae13ea
master
% echo $?
0
  • Die Ausgabe erfolgt auf STDOUT
  • Der Ausstiegswert ist 0 .

Commit von mehreren Filialen aus erreichbar

% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
  • Die Ausgabe erfolgt an STDERR
  • Der Ausgangswert ist 1 .

Aufgrund des Exit-Status kann auf diesen sicher aufgebaut werden. Zum Beispiel, um die für den Abruf verwendete Fernbedienung zu erhalten:

remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"

0 Stimmen

Ich musste googeln, was erreichbar bedeutet, und was ich fand, war, dass das Commit erreichbar ist, wenn es erreichbar ist, wenn man den übergeordneten Links folgt. Für mich war das ein Aha-Erlebnis, da ich anfangs dachte, wenn es eine Baumstruktur ist, dann sind alle Knoten erreichbar, wenn man in jede Richtung gehen kann, das ist nicht der Fall, es ist nur eine übergeordnete Richtung - bitte korrigiert mich, wenn ich falsch liege

0voto

Yates Zhou Punkte 41

Ich denke, jemand sollte vor dem gleichen Problem stehen, dass er die Verzweigung nicht herausfinden kann, obwohl sie tatsächlich in einer Verzweigung existiert.

Ziehen Sie lieber erst alle:

git pull --all

Führen Sie dann die Verzweigungssuche durch:

git name-rev <SHA>

oder:

git branch --contains <SHA>

-1voto

Gary Lyn Punkte 1078

So finden Sie die örtliche Niederlassung:

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

Um den entfernten Zweig zu finden:

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

2 Stimmen

Einige Erläuterungen zu Ihren Beispielen wären toll

-6voto

Amber Punkte 473552

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

8 Stimmen

Ich möchte das eigentlich nicht abwerten, denn streng genommen stimmt es, dass Git diese Informationen nicht dauerhaft speichert, aber es ist sehr oft möglich, sie trotzdem herauszufinden. Siehe meine Antwort.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X