So finden Sie das nächste übergeordnete Element eines Git-Zweigs

Lesezeit: 13 Minuten

So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Peter Bauer

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’ Freigabecodeund feature ist eine neue Funktion in Vorbereitung develop.

Mit Hooks möchte ich Pushes ablehnen können feature zu meinem Remote-Repository, es sei denn, es wird festgeschrieben f ist ein direkter Nachkomme von develop KOPF. Dh der Commit-Baum sieht so aus, weil Feature wurde git rebase an d.

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

Ist es also möglich:

  • Identifizieren Sie den übergeordneten Zweig von feature?
  • Identifizieren Sie das Commit im übergeordneten Zweig which f ist ein Nachkomme von?

Von dort aus würde ich überprüfen, was HEAD des übergeordneten Zweigs ist, und sehen, ob f Vorgänger stimmt mit HEAD des übergeordneten Zweigs überein, um zu bestimmen, ob das Feature rebasiert werden muss.

  • Diese Frage sollte umformuliert werden, um den Elternteil eines Elternteils zu finden.

    – Tim Boland

    3. Mai 2018 um 17:11 Uhr

  • Im Allgemeinen verwende ich git log --first-parentes werden alle Commits aus dem aktuellen Zweig angezeigt, danach werden der übergeordnete Zweig und seine Commits angezeigt

    – Vipul Patil

    6. Oktober 2021 um 10:18 Uhr

1646879896 439 So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Chris Johnsen

Angenommen, das Remote-Repository verfügt über eine Kopie der entwickeln branch (Ihre anfängliche Beschreibung beschreibt es in einem lokalen Repository, aber es hört sich so an, als ob es auch in einem entfernten Repository existiert), sollten Sie in der Lage sein, das zu erreichen, was Sie meiner Meinung nach wollen, aber der Ansatz unterscheidet sich etwas von dem, was Sie sich vorgestellt haben.

Die Geschichte von Git basiert auf a DAG von Commits. Branches (und „refs“ im Allgemeinen) sind nur vorübergehende Bezeichnungen, die auf bestimmte Commits im kontinuierlich wachsenden Commit-DAG verweisen. Daher kann sich die Beziehung zwischen Zweigen im Laufe der Zeit ändern, die Beziehung zwischen Commits jedoch nicht.

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

Es sieht aus wie baz basiert auf (einer alten Version von) bar? Aber was ist, wenn wir löschen bar?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

Jetzt sieht es so aus baz basiert auf foo. Aber die Abstammung von baz änderte sich nicht. Wir haben gerade ein Label entfernt (und den daraus resultierenden Dangling Commit). Und was ist, wenn wir unter ein neues Label hinzufügen? 4?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

Jetzt sieht es so aus baz basiert auf quux. Die Abstammung änderte sich jedoch nicht, nur die Etiketten änderten sich.

Wenn wir jedoch fragten: „ist begangen 6 ein Nachkomme von Commit 3?” (vorausgesetzt 3 und 6 vollständige SHA-1-Commit-Namen sind), dann wäre die Antwort „ja“, ob die bar und quux Etiketten vorhanden sind oder nicht.

Sie könnten also Fragen stellen wie „Ist der gepushte Commit ein Nachkomme des aktuellen Tipp der entwickeln branch?”, aber Sie können nicht zuverlässig fragen: “Was ist der übergeordnete Branch des gepushten Commits?”.

Eine meist zuverlässige Frage, die dem, was Sie wollen, nahe zu kommen scheint, ist:

Für alle Vorfahren des gepushten Commits (mit Ausnahme der aktuellen Spitze von entwickeln und seine Vorfahren), die die aktuelle Spitze haben entwickeln als Elternteil:

  • Gibt es mindestens ein solches Commit?
  • Sind alle diese Commits Single-Eltern-Commits?

Was umgesetzt werden könnte als:

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

Dies wird einiges von dem abdecken, was Sie einschränken möchten, aber vielleicht nicht alles.

Als Referenz finden Sie hier eine erweiterte Beispielhistorie:

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \
                        R---S

Der obige Code könnte zum Ablehnen verwendet werden Hund S beim Akzeptieren H', J, Koder Nwürde es aber auch akzeptieren L und P (Sie beinhalten Zusammenführungen, aber sie führen nicht die Spitze von zusammen entwickeln).

Auch abzulehnen L und PSie können die Frage ändern und stellen

Für alle Vorfahren des gepushten Commits (mit Ausnahme der aktuellen Spitze von entwickeln und seine Vorfahren):

  • Gibt es Verpflichtungen mit zwei Elternteilen?
  • Wenn nicht, hat mindestens ein solcher Commit den aktuellen Tipp von entwickeln sein (einziger) Elternteil?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac

  • Ich bekomme das: git: fatal: mehrdeutiges Argument ‘…’: sowohl Revision als auch Dateiname. Was ist die Absicht der drei Punkte?

    – Jack Ukleja

    13. Oktober 2015 um 11:02 Uhr

  • @Schneider Ich bin mir ziemlich sicher, dass das ‘…’ in diesem Beispiel als Platzhalter dienen soll: Wenn Sie es durch den SHA des Commit ersetzen, gegen das Sie diese Überprüfung durchführen möchten (z. B. den HEAD des Zweigs Sie gerade eingeschaltet sind), funktioniert alles einwandfrei.

    – Daniel Brady

    5. August 2017 um 23:04 Uhr

  • Danke für diese ausführliche Antwort! Es ist super nützlich. Ich möchte einen ähnlichen Haken machen, aber ich möchte den Namen des Entwicklungszweigs nicht fest codieren. Das heißt, ich möchte einen Hook, um eine Rebase auf einen anderen Zweig als den übergeordneten Zweig zu verhindern. Wenn ich Ihre Antwort gut verstehe (ich bin neu in Bash und so), ist dies nicht in Ihrer Antwort enthalten, oder? Gibt es eine Möglichkeit, dies zu tun?

    – Kemeia

    20. Dezember 2017 um 15:02 Uhr


  • Ich schätze den T-Rex, der eine Flaggen- (oder Fleischerbeil-) Verlaufsgrafik hält

    – Graham Russel

    14. April 2020 um 12:29 Uhr


  • @GrahamRussell: In einem früheren Kommentar vor einigen Jahren wurde es als Velociraptor bezeichnet, aber dieser Kommentar scheint seit einiger Zeit gelöscht worden zu sein.

    – Torek

    11. März 2021 um 23:48 Uhr

So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Joe Chrysler

Eine Umschreibung

Eine andere Möglichkeit, die Frage zu formulieren, lautet: “Was ist das nächste Commit, das sich auf einem anderen Zweig als dem aktuellen Zweig befindet, und welcher Zweig ist das?”

Eine Lösung

Sie können es mit ein wenig Kommandozeilen-Magie finden

git show-branch \ |  sed "s/].*//" \ |  grep "\*" \ |  grep -v "$(git rev-parse --abbrev-ref HEAD)" \ |  Kopf -n1 \ |  sed "s/^.*\[//"

With AWK:

git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \ |  awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'

So funktioniert das:

  1. Zeigen Sie einen Textverlauf aller Commits an, einschließlich Remote-Branches.
  2. Ancestors des aktuellen Commits sind durch einen Stern gekennzeichnet. Alles andere herausfiltern.
  3. Ignorieren Sie alle Commits im aktuellen Zweig.
  4. Das erste Ergebnis ist der nächste Vorfahrenzweig. Ignorieren Sie die anderen Ergebnisse.
  5. Filialnamen werden angezeigt [in brackets]. Ignoriere alles außerhalb der Klammern und die Klammern.
  6. Manchmal enthält der Zweigname a ~# oder ^# um anzugeben, wie viele Commits zwischen dem referenzierten Commit und der Verzweigungsspitze liegen. Es ist uns egal. Ignoriere sie.

Und das Ergebnis

Führen Sie den obigen Code aus

 A---B---D <-master
      \
       \
        C---E---I <-develop
             \
              \
               F---G---H <-topic

Werde dir geben develop wenn Sie es von H ausführen und master wenn Sie es von I ausführen.

Der Code ist als Gist verfügbar.

  • Einen abschließenden Backtick entfernt, der einen Fehler verursachte. Wenn ich diesen Befehl ausführe, erhalte ich jedoch eine große Anzahl von Warnungen, in denen ich mich über jeden Zweig beschwere, der sagt cannot handle more than 25 refs

    – Jon L.

    25. März 2014 um 13:00 Uhr

  • @JoeChrysler denkst du, du kannst es zu einer Zeile statt zu 2 machen und es möglicherweise auf dem Mac so funktionieren lassen ack ist auf dem Mac nicht verfügbar (jemand schlug vor, ack mit grep)

    – Nichtpolarität

    18. April 2014 um 17:19 Uhr

  • Entschuldigung, das ist falsch. Hier ist die richtige, die für mich funktioniert hat: git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

    – Droidbot

    25. April 2014 um 16:54 Uhr


  • @droidbot Nett, muss aber neu angeordnet werden, um das Entfernen von Refs zu vermeiden, wenn grep -v catch commit message oder Ihr Branch-Name Teil eines anderen Branch-Namens ist. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | Kopf -n1 | sed "s/^.*\[//"

    – gaal

    Jul 27, 2015 at 13:12


  • @OlegAbrazhaev I dont know if you ever got your question answered. using the git alias of: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #" funktioniert bei mir

    – mduttondev

    29. März 2018 um 20:13 Uhr

So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Nikhil CM

Git-Elternteil

Sie können den Befehl einfach ausführen

git parent

um das übergeordnete Element des Zweigs zu finden, wenn Sie die Antwort von Joe Chrysler als a hinzufügen Git-Alias. Es wird die Verwendung vereinfachen.

Öffne das gitconfig Datei befindet sich unter "~/.gitconfig" mit einem beliebigen Texteditor (für Linux). Und für Windows befindet sich der Pfad “.gitconfig” im Allgemeinen unter C:\users\your-user\.gitconfig.

vim  ~/.gitconfig

Fügen Sie den folgenden Alias-Befehl in der Datei hinzu:

[alias]
    parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"

Speichern und beenden Sie den Editor.

Führen Sie den Befehl aus git parent.

Das ist es!

  • Dies ist eine großartige Lösung. Es wäre hilfreich, auch einige Beispielausgaben hinzuzufügen, um die erwarteten Ergebnisse sicherzustellen. Als ich es ausführte, erhielt ich einige Warnungen vor der allerletzten Zeile, von der ich glaube, dass sie der Name des übergeordneten Zweigs war.

    – Tempel

    21. September 2018 um 17:09 Uhr


  • Klappt wunderbar! Für Windows-Benutzer befindet sich die .gitconfig im Allgemeinen unter c:\users\your-user\.gitconfig

    – zion

    9. November 2018 um 17:35 Uhr

  • Bekommen cannot handle more than 25 refs Ausnahme.

    – Schajin

    18. Februar 2019 um 7:49 Uhr

  • Kann jemand dies bearbeiten, um die Warnung zu behandeln? @ttemple, kannst du?

    – NICHIL CM

    11. April 2019 um 12:48 Uhr

  • @NIKHILCM arbeitet wie ein Champion. Aber ich habe hier eine Frage, ob der Elternteil angibt, von wo aus der Zweig erstellt wurde, oder etwas anderes?

    – Hariprasath

    11. Dezember 2019 um 14:25 Uhr

1646879897 29 So finden Sie das nachste ubergeordnete Element eines Git Zweigs
rcde0

Sie können auch versuchen:

git log --graph --decorate

Ich habe eine Lösung für Ihr Gesamtproblem (bestimmen Sie, ob feature stammt von der Spitze ab develop), aber es funktioniert nicht mit der von Ihnen beschriebenen Methode.

Sie können verwenden git branch --contains um alle Zweige aufzulisten, die von der Spitze abstammen developdann benutze grep sichergehen feature ist unter ihnen.

git branch --contains develop | grep "^ *feature$"

Wenn es darunter ist, wird es gedruckt " feature" auf die Standardausgabe und haben einen Rückgabecode von 0. Andernfalls wird nichts gedruckt und der Rückgabecode ist 1.

  • Dies funktioniert, aber es sollte beachtet werden, dass es bei einem Repository mit vielen Refs lange dauern kann. Das macht es ein bisschen weniger als ideal zum Einlaufen, zB in einen Pre-Receive-Hook.

    – ebneter

    19. Januar 2016 um 0:24 Uhr

  • Ich suchte die Filiale, wir nennen sie <branch>wo ich aufgetreten bin: git checkout -b <branch-2> von… DAS ist die Antwort! Keine Notwendigkeit für grep, wirklich. git branch --contains <branch>

    – Bikameraler Geist

    17. Juli 2019 um 20:29 Uhr


  • Dies ist die Antwort, um Kinder zu finden

    – CervEd

    30. September 2021 um 8:51 Uhr

1646879897 3 So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Peter Mortensen

Das funktioniert gut für mich:

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Höflichkeitskommentar und Antworten von droidbot und @Jistanidiot.

  • Dies funktioniert, aber es sollte beachtet werden, dass es bei einem Repository mit vielen Refs lange dauern kann. Das macht es ein bisschen weniger als ideal zum Einlaufen, zB in einen Pre-Receive-Hook.

    – ebneter

    19. Januar 2016 um 0:24 Uhr

  • Ich suchte die Filiale, wir nennen sie <branch>wo ich aufgetreten bin: git checkout -b <branch-2> von… DAS ist die Antwort! Keine Notwendigkeit für grep, wirklich. git branch --contains <branch>

    – Bikameraler Geist

    17. Juli 2019 um 20:29 Uhr


  • Dies ist die Antwort, um Kinder zu finden

    – CervEd

    30. September 2021 um 8:51 Uhr

1646879898 628 So finden Sie das nachste ubergeordnete Element eines Git Zweigs
Matt Stuvysant

Eine Lösung

Die Lösung basiert auf git show-branch hat bei mir nicht ganz funktioniert (siehe unten), also habe ich es mit dem basierend auf kombiniert git log und endete damit:

git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
      | grep -v "(HEAD" \                               # removes current head (and branch)
      | head -n1 \                                      # selects only the closest decoration
      | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
      | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
      | sed 's/origin\///'                              # strips "origin/" from the decoration

Einschränkungen und Vorbehalte

  • HEAD kann getrennt werden (viele CI-Tools tun dies, um sicherzustellen, dass sie den richtigen Commit in einem bestimmten Zweig erstellen), aber Ursprungsniederlassung und Ortsniederlassung müssen beides sein gleich oder “über” der aktuelle KOPF.
  • Da muss sein keine Tags im Weg (ich nehme an; ich habe das Skript nicht auf Commits mit einem Tag zwischen untergeordnetem und übergeordnetem Zweig getestet)
  • das Drehbuch stützt sich auf die Tatsache “KOPF” ist immer als erste Dekoration aufgeführt bis zum log Befehl
  • Laufen das Skript an master und develop resultiert (meistens) in <SHA> Initial commit

Die Ergebnisse

 A---B---D---E---F <-origin/master, master
      \      \
       \      \
        \      G---H---I <- origin/hotfix, hotfix
         \
          \
           J---K---L <-origin/develop, develop
                \
                 \
                  M---N---O <-origin/feature/a, feature/a
                       \   \
                        \   \
                         \   P---Q---R <-origin/feature/b, feature/b
                          \
                           \
                            S---T---U <-origin/feature/c, feature/c

Trotz lokaler Filialexistenz (zB nur origin/topic ist seit dem Commit vorhanden O direkt von seinem SHA ausgecheckt wurde), sollte das Skript wie folgt ausgeben:

  • Für Zusagen G, H, I (sich verzeigen hotfix) → master
  • Für Zusagen M, N, O (sich verzeigen feature/a) → develop
  • Für Zusagen S, T, U (sich verzeigen feature/c) → develop
  • Für Zusagen P, Q, R (sich verzeigen feature/b) → feature/a
  • Für Zusagen J, K, L (sich verzeigen develop) → <sha> Initial commit*
  • Für Zusagen B, D, E, F (sich verzeigen master) → <sha> Initial commit

* – oder master wenn developDie Commits von lagen über dem HEAD des Masters (~ der Master wäre für die Entwicklung schnell vorspulbar)


Warum hat Show-Zweig für mich nicht funktioniert

Die Lösung basiert auf git show-branch hat sich für mich in folgenden Situationen als unzuverlässig erwiesen:

  • abgetrennter KOPF – einschließlich abgenommenem Kopfgehäuse bedeutet Austausch grep '\*' \ für `grep ‘!’ \ – und das ist erst der Anfang aller Probleme
  • Laufen das Skript an master und develop ergibt sich develop bzw. “
  • Zweige an master sich verzeigen (hotfix/ Zweige) enden mit der develop als Eltern seit ihrer engsten master Branch Parent wurde mit markiert ! anstatt * aus einem Grund.

  • Nur eine Antwort, die funktioniert hat – als Git-Alias: "!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"

    – Ian Kemp

    2. Mai 2019 um 10:42 Uhr

  • Dieser Befehl hat bei mir funktioniert git log –decorate –simplify-by-decoration –oneline | grep -v “(HEAD” | Kopf -n1 | sed ‘s/.* ((.*)) .*/\1/’ | sed ‘s/(.*), .*/\1/’ | sed ‘s/herkunft\///’

    – Bravo

    18. Dezember 2020 um 4:35 Uhr

  • Dies sollte die akzeptierte Antwort sein :/

    – Meredith

    4. Dezember 2021 um 8:05 Uhr

985730cookie-checkSo finden Sie das nächste übergeordnete Element eines Git-Zweigs

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy