611 Stimmen

So finden Sie den nächstgelegenen Elternteil eines Git-Zweigs

Nehmen wir an, ich habe das folgende lokale Repository mit einem Commit-Baum wie diesem:

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

master ist mein dies ist der neueste stabile Release-Code , develop ist mein dies ist der "nächste" Freigabecode und feature ist eine neue Funktion, die in Vorbereitung ist für develop .

Mit Hilfe von Hooks möchte ich Pushes verweigern können an feature in mein entferntes Repository zu übertragen, es sei denn f ist ein direkter Abkömmling von develop HEAD. D.h. der Commit-Baum sieht so aus, weil das Feature git rebase auf d .

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

Ist es also möglich,:

  • Identifizieren Sie den übergeordneten Zweig von feature ?
  • Identifizieren Sie die Übertragung im übergeordneten Zweig, die f ist ein Nachkomme von?

Von dort aus würde ich prüfen, was HEAD des übergeordneten Zweigs ist, und sehen, ob f Vorgänger mit dem übergeordneten Zweig HEAD übereinstimmt, um festzustellen, ob das Merkmal neu geordnet werden muss.

8voto

VonC Punkte 1117238

Denken Sie daran, dass, wie in "Git: Herausfinden, von welchem Zweig ein Commit stammt" können Sie den Zweig, in dem diese Übergabe stattgefunden hat, nicht ohne Weiteres ermitteln (Zweige können umbenannt, verschoben, gelöscht werden...), auch wenn git branch --contains <commit> ist ein Anfang.

  • Sie können von Commit zu Commit zurückgehen, bis git branch --contains <commit> listet nicht die feature Verzweigung und Liste develop Zweigstelle,
  • vergleichen Sie diese SHA1-Übertragung mit /refs/heads/develop

Wenn die beiden Commits id übereinstimmen, sind Sie startklar (das würde bedeuten, dass die feature Zweig hat seinen Ursprung im HEAD von develop ).

8voto

user1529413 Punkte 341

Ich behaupte nicht, dass dies ein guter Weg ist, um das Problem zu lösen, aber für mich scheint es zu funktionieren:

git branch --contains $(cat .git/ORIG_HEAD)

Das Problem dabei ist, dass das Cat'ing einer Datei einen Einblick in das Innenleben von Git bedeutet, so dass dies nicht unbedingt vorwärtskompatibel (oder rückwärtskompatibel) ist.

7voto

chrisevett Punkte 616

Hier ist eine PowerShell-Implementierung von Mark Reeds Lösung :

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }

7voto

Mark Reed Punkte 85468

Joe Chryslers Befehlszeilenzauber kann vereinfacht werden. Hier ist Joes Logik - der Kürze halber habe ich einen Parameter namens cur_branch anstelle der Befehlssubstitution `git rev-parse --abbrev-ref HEAD` in beide Versionen; das kann wie folgt initialisiert werden:

cur_branch=$(git rev-parse --abbrev-ref HEAD)

Dann ist da noch Joes Pipeline:

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

Wir können das Gleiche wie alle fünf dieser einzelnen Befehlsfilter mit einem relativ einfachen awk Befehl:

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'

Das sieht folgendermaßen aus:

-F'[]^~[]'

Aufteilung der Zeile in Felder bei ] , ^ , ~ und [ Zeichen.

/\*/

Zeilen suchen, die ein Sternchen enthalten

&& !/'"$cur_branch"'/

...aber nicht der Name des aktuellen Zweigs

{ print $2;

Wenn Sie eine solche Zeile finden, drucken Sie deren zweites Feld (d.h. den Teil zwischen dem ersten und dem zweiten Vorkommen unserer Feldtrennzeichen). Bei einfachen Verzweigungsnamen ist das nur das, was zwischen den Klammern steht; bei Verweisen mit relativen Sprüngen ist es nur der Name ohne den Modifikator. Unser Satz von Feldtrennzeichen erfüllt also die Absicht von beiden sed Befehle.

  exit }

Verlassen Sie dann sofort den Raum. Das bedeutet, dass immer nur die erste übereinstimmende Zeile verarbeitet wird, so dass wir die Ausgabe nicht durch die Pipeline leiten müssen head -n 1 .

3 Stimmen

Beachten Sie, dass einige Zweige in der Ausgabe fehlen können, weil zu viele Verweise vorhanden sind. Sie werden stattdessen als Warnungen auf stderr angezeigt.

0 Stimmen

Auch cannot handle more than 26 refs .

4voto

Haoyang Feng Punkte 150

Verwendung:

vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Sie erreicht die gleichen Ziele wie Mark Reeds Antwort aber es verwendet einen viel sichereren Ansatz, der in einer Reihe von Szenarien nicht zu Fehlverhalten führt:

  1. Die letzte Übergabe des übergeordneten Zweigs ist eine Zusammenführung, so dass die Spalte zeigt - pas *
  2. Commit-Nachricht enthält einen Zweignamen
  3. Die Commit-Nachricht enthält *

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