Jak znaleźć najbliższego rodzica gałęzi Git?

Załóżmy, że mam następujące lokalne repozytorium z drzewem commitów:

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

master is my to jest najnowszy stabilny kod Wydania, develop Czy mój to jest "następny" kod Wydania, a feature to nowa funkcja przygotowywana dla develop.

To, co chcę zrobić na moim zdalnym repo używając hooków, to odrzucić wypychanie feature, chyba że commit f jest bezpośrednim potomkiem develop HEAD. tj. drzewo commit wygląda to tak, ponieważ funkcja została git rebase na d.

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

Więc jest możliwe:

  • zidentyfikować oddział macierzysty feature?
  • Zidentyfikuj commit w gałęzi nadrzędnej, której f jest potomkiem?

Stamtąd chciałbym sprawdzić, co to jest HEAD gałęzi nadrzędnej, i zobaczyć, czy f poprzednik pasuje do głowicy gałęzi nadrzędnej, aby określić, czy funkcja wymaga rebasowania.

 449
Author: Scott, 2010-07-01

23 answers

Zakładając, że zdalne repozytorium posiada kopię gałęzi develop (Twój początkowy opis opisuje to w lokalnym repozytorium, ale wygląda na to, że istnieje również w zdalnym), powinieneś być w stanie osiągnąć to, co myślę, że chcesz, ale podejście jest nieco inne od tego, co sobie wyobrażałeś.

Historia Gita opiera się na dag commitów. Gałęzie (i ogólnie "refs") są tylko przejściowymi etykietami, które wskazują na konkretne commity w ciągłym rośnie w zaroślach. Jako takie, relacje między gałęziami mogą się zmieniać w czasie, ale relacje między commitami nie.

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

Wygląda na to, że baz jest oparta na (starej wersji) bar? Ale co jeśli usuniemy bar?

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

Teraz wygląda na to, że baz opiera się na foo. Ale pochodzenie baz się nie zmieniło, po prostu usunęliśmy etykietę (i wynikający z niej zwisający commit). A co jeśli dodamy nową etykietę na 4?

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

Teraz wygląda na to, że baz jest na podstawie quux. Mimo to pochodzenie nie uległo zmianie, zmieniły się tylko etykiety.

Jeśli jednak zapytamy: "czy commit 6jest potomkiem commita 3?"(zakładając, że 3 i 6 są pełnymi nazwami commitów SHA-1), wtedy odpowiedź brzmiałaby" tak", niezależnie od tego, czy etykiety bar i quux są obecne, czy nie.

Można więc zadawać pytania typu " czy wciśnięty commit jest potomkiem obecnego wierzchołka rozwiń gałąź?", ale nie można niezawodnie zapytać "co to jest nadrzędna gałąź forsowanego commita?".

Najbardziej wiarygodnym pytaniem, które wydaje się zbliżać do tego, czego chcesz, jest:]}

Dla wszystkich przodków popchniętego commita (z wyłączeniem bieżącej końcówki rozwijają i jego przodków), które mają bieżącą końcówkę rozwijają jako rodzica:

  • czy istnieje przynajmniej jeden taki commit?
  • czy wszystkie takie commity są commitami samotnego rodzica?

Które można wdrożyć as:

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

To pokryje część tego, co chcesz ograniczyć, ale może nie wszystko.

Dla odniesienia, oto Rozszerzona historia przykładu:

    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

Powyższy kod może być użyty do odrzucenia H i S podczas przyjmowania H', J, K, lub N, ale przyjmowałoby również L i P (wiążą się z połączeniami, ale nie łączą końcówki rozwijają).

Aby również odrzucić L i P, możesz zmienić pytanie i zapytaj

Dla wszystkich przodków (z wyłączeniem obecnego wierzchołka rozwijają się i jego przodków):

  • czy są jakieś zobowiązania z dwójką rodziców?
  • jeśli nie, to czy przynajmniej jeden taki commit ma bieżącą końcówkęrozwija swojego (jedynego) rodzica?
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
 362
Author: Chris Johnsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-08 20:06:30

A rephrasal

Innym sposobem wyrażenia tego pytania jest "jaki jest najbliższy commit, który znajduje się na gałęzi innej niż bieżąca i która to gałąź?"

A solution

Możesz go znaleźć za pomocą odrobiny magii linii poleceń

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

Z 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 )}'

Oto Jak to działa:

  1. Wyświetla historię tekstową wszystkich commitów, łącznie ze zdalnymi gałęziami.
  2. przodkowie aktualnego commita są wskazywani przez star. Odfiltruj Wszystko inne.
  3. ignoruje wszystkie commity w bieżącej gałęzi.
  4. pierwszy wynik będzie najbliższą gałęzią przodka. Zignoruj Pozostałe wyniki.
  5. nazwy gałęzi są wyświetlane [w nawiasach]. Ignoruj wszystko poza nawiasami i nawiasami.
  6. czasami nazwa gałęzi będzie zawierać ~ # lub ^#, aby wskazać, ile commitów znajduje się pomiędzy odwołanym commitem a końcówką gałęzi. Nie obchodzi nas to. Zignoruj ich.

I Wynik

Uruchamianie powyższego kodu na

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

Da ci develop jeśli uruchomisz go z H I master jeśli uruchomisz go z I.

Kod jest dostępny jako gist

 271
Author: Joe Chrysler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-05 12:30:53

Możesz również spróbować:

git log --graph --decorate
 122
Author: rcde0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-29 20:44:02

Git parent

Możesz po prostu uruchomić polecenie

git parent

Aby znaleźć rodzica gałęzi, dodaj odpowiedź @Joe Chrysler jako alias git . Uprości to Korzystanie.

Otwórz plik gitconfig znajdujący się w "~/.gitconfig" używając dowolnego edytora tekstu. (Dla Linuksa). I dla okien ".gitconfig " ścieżka znajduje się zazwyczaj w c:\users\your-user\.gitconfig

vim  ~/.gitconfig

Dodaj do pliku następujące polecenie alias:

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

Zapisz i wyjdź z redaktor.

Uruchom polecenie git parent

To jest to!
 121
Author: NIKHIL C M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-19 07:30:47

Mam rozwiązanie twojego ogólnego problemu( określ, czy {[1] } pochodzi od końcówki develop), ale nie działa przy użyciu metody, którą opisałeś.

Możesz użyć git branch --contains, aby wyświetlić listę wszystkich gałęzi pochodzących z końcówki develop, a następnie użyć grep, aby upewnić się, że feature jest wśród nich.

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

Jeśli jest wśród nich, wyświetli " feature" na standardowe wyjście i będzie miał kod powrotu równy 0. W przeciwnym razie nic nie wydrukuje i będzie miał kod zwrotny równy 1.

 53
Author: Daniel Stutzbach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-01 20:29:38

To działa dobrze dla mnie.

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
[[1]}uprzejme odpowiedzi od: @ droidbot i @Jistanidiot
 47
Author: Murali Mopuru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 17:43:45

Ponieważ żadna z powyższych odpowiedzi nie działa na naszym repozytorium, chcę podzielić się swoją własną drogą, używając najnowszych mergów w git log:

#!/bin/bash
git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 10

Umieść go w skrypcie o nazwie git-last-merges, który również przyjmuje nazwę gałęzi jako argument (zamiast bieżącej gałęzi), a także inne argumenty git log

Z wyjścia możemy ręcznie wykryć gałąź (- y) nadrzędną (- e) na podstawie własnych konwencji rozgałęzień i liczby scaleń z każdej gałęzi.

EDIT: Jeśli często używasz git rebase na gałęziach potomnych (a merge sÄ ... czÄ ™ sto przekazywane szybko, wiÄ ™ c nie ma zbyt wielu zmian scalajÄ ... cych), ta odpowiedĹş nie bÄ ™ dzie dziaĹ ' aĹ 'a dobrze, wiÄ ™ c napisaĹ' em skrypt, ktĂłry liczyĺ ' przed commitami (normal i merge), a za commitami (nie powinno byÄ ‡ Ĺźadnych za merge w branĹźy macierzystej) na wszystkich branĺźach w porăłwnaniu do obecnej branĹźy. Po prostu uruchom ten skrypt i daj mi znać, czy działa dla Ciebie, czy nie

#!/bin/bash
HEAD="`git rev-parse --abbrev-ref HEAD`"
echo "Comparing to $HEAD"
printf "%12s  %12s   %10s     %s\n" "Behind" "BehindMerge" "Ahead" "Branch"
git branch | grep -v '^*' | sed 's/^\* //g' | while read branch ; do
    ahead_merge_count=`git log --oneline --merges $branch ^$HEAD | wc -l`
    if [[ $ahead_merge_count != 0 ]] ; then
        continue
    fi
    ahead_count=`git log --oneline --no-merges $branch ^$HEAD | wc -l`
    behind_count=`git log --oneline --no-merges ^$branch $HEAD | wc -l`
    behind_merge_count=`git log --oneline --merges ^$branch $HEAD | wc -l`
    behind="-$behind_count"
    behind_merge="-M$behind_merge_count"
    ahead="+$ahead_count"
    printf "%12s  %12s   %10s     %s\n" "$behind" "$behind_merge" "$ahead" "$branch"
done | sort -n
 12
Author: saeedgnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-30 07:34:07

Rozwiązanie

Rozwiązanie oparte na git show-branch nie do końca działa dla mnie (patrz niżej), więc połączyłem go z jednym na podstawie git log i skończyło się na tym:

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

Ograniczenia i zastrzeżenia

  • HEAD może być odłączony (wiele narzędzi CI robi to, aby mieć pewność, że zbudują poprawny commit w danej gałęzi), ale origin branch I local branch muszą być zarówno w par lub "powyżej" bieżącej gałęzi.
  • musi być brak znaczników w sposób (zakładam, że nie testowałem skryptu na commitach z tagiem między potomkiem a gałęzią nadrzędną)
  • skrypt opiera się na fakcie "HEAD" jest zawsze wymienione jako pierwsza Dekoracja przez log
  • uruchamianie skryptu na master i develop wyniki (głównie) w <SHA> Initial commit

Wyniki

 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

Pomimo istnienia lokalnej gałęzi (np. tylko origin/topic jest obecny od commit O w 1996 roku, po raz pierwszy w historii, w 1997 roku, w Polsce, w 1998 roku, w Polsce, w 1999 roku, w Polsce i na świecie.]}

  • dla commitów G, H, I (oddział hotfix) → master
  • dla commitów M, N, O (oddział feature/a) → develop
  • dla commitów S, T, U (oddział feature/c) → develop
  • dla commitów P, Q, R (oddział feature/b) → feature/a
  • dla commitów J, K, L (oddział develop) → <sha> Initial commit*
  • dla commitów B, D, E, F (Oddział master) → <sha> Initial commit
W przeciwieństwie do poprzednich wersji, Master nie może być modyfikowany w taki sposób, że nie może być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby nie mógł być modyfikowany w taki sposób, aby]}

Dlaczego nie pokazałeś-branch działa dla mnie

Rozwiązanie oparte na git show-branch okazało się zawodne dla mnie w następujących sytuacjach:

  • Głowa wolnostojąca - w tym Głowa wolnostojąca case oznacza zamianę grep '\*' \ na 'grep'!'\- a to dopiero początek wszystkich kłopotów
  • uruchamianie skryptu na master i develop wyniki w develop i ` odpowiednio
  • gałęzie na master branch (hotfix/ Branch) kończy się develop jako rodzic, ponieważ ich najbliższy rodzic master został oznaczony ! zamiast * nie bez powodu.
 11
Author: Matt Stuvysant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-19 10:07:46

Pamiętaj, że jak opisano w "Git: Finding what branch a commit came from" , nie możesz łatwo wskazać gałęzi, z której został utworzony commit (gałęzie mogą być zmieniane, przenoszone, usuwane...), choć git branch --contains <commit> to początek.

  • Możesz wrócić z commit do commit, dopóki git branch --contains <commit> nie wyświetli gałęzi feature oraz listy gałęzi develop,
  • porównaj ten commit SHA1 do /refs/heads/develop

Jeśli dwa commity id pasują, możesz iść (oznaczałoby to feature oddział ma swój początek na czele develop).

 8
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

Oto implementacja PowerShell rozwiązania Marka Reeda:

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }
 6
Author: chrisevett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-29 20:43:14

Magia wiersza poleceń Joechryslera może być uproszczona. Oto logika Joego - dla zwięzłości wprowadziłem parametr o nazwie cur_branch w miejsce zastąpienia polecenia `git rev-parse --abbrev-ref HEAD` w obu wersjach; można go zainicjować w następujący sposób:

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

Oto rurociąg Joe:

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

Możemy wykonać to samo, co wszystkie pięć tych pojedynczych filtrów poleceń w stosunkowo prostym poleceniu awk:

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

To rozkłada się tak:

-F'[]^~[]' 

Split the linia do pól w ], ^, ~, i [ znaków.

/\*/                      

Znajdź linie zawierające gwiazdkę

&& !/'"$cur_branch"'/

...ale nie obecna nazwa gałęzi

{ print $2;               

Gdy znajdziesz taką linię, wydrukuj jej drugie pole(to znaczy część pomiędzy pierwszym i drugim wystąpieniem naszych znaków separatora pól). Dla prostych nazw gałęzi, będzie to tylko to, co znajduje się między nawiasami; dla refów ze skokami względnymi, będzie to tylko nazwa bez modyfikatora. Więc nasz zestaw separatorów pól obsługuje intencje obu komend sed.

  exit }

Następnie NATYCHMIAST WYJDŹ. Oznacza to, że przetwarza tylko pierwszą pasującą linię, więc nie musimy przepuszczać wyjścia przez head -n 1.

 6
Author: Mark Reed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-10 12:38:46

Nie mówię, że to dobry sposób na rozwiązanie tego problemu, jednak wydaje się, że to działa na mnie.

git branch --contains $(cat .git/ORIG_HEAD) Problem polega na tym, że cat'ing pliku zagląda do wewnętrznego działania Gita, więc niekoniecznie jest to kompatybilne do przodu (lub wstecznie).

 5
Author: user1529413,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 15:39:09

Implementacja wieloplatformowa z Ant

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />
 3
Author: ENargit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-30 06:53:07

@Mark Reed: powinieneś dodać, że linia zatwierdzania nie powinna zawierać tylko gwiazdkę, ale powinna zaczynać się od gwiazdki! W przeciwnym razie komunikaty zatwierdzające zawierające gwiazdkę są również dołączane do dopasowanych linii. Tak powinno być:

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

Lub wersja długa:

git show-branch -a           |
  awk '^\*'                  | # we want only lines that contain an asterisk
  awk -v "$current_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`
 2
Author: ladiko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-27 18:30:40
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/[\^~].*//'

Osiąga te same cele, Co odpowiedź Marka Reeda, ale używa znacznie bezpieczniejszego podejścia, które nie źle się zachowuje w wielu scenariuszach:

  1. Ostatni commit gałęzi nadrzędnej jest scaleniem, co sprawia, że kolumna pokazuje - nie *
  2. Commit zawiera nazwę gałęzi
  3. Commit message contains *
 2
Author: Haoyang Feng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-11 10:03:03

Oto moja wersja Powershell:

function Get-GHAParentBranch {
    [CmdletBinding()]
    param(
        $Name = (git branch --show-current)
    )
    git show-branch | 
      Select-String '^[^\[]*\*' | 
      Select-String -NotMatch -Pattern "\[$([Regex]::Escape($Name)).*?\]" |
      Select-Object -First 1 |
      Foreach-Object {$PSItem -replace '^.+?\[(.+)\].+$','$1'}
}
 1
Author: Justin Grote,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 17:10:18

Rozwiązania oparte na git show-branch -a plus niektóre filtry mają jeden minus: git może rozważyć nazwę gałęzi o krótkim czasie życia.

Jeśli masz kilku możliwych rodziców, na których Ci zależy, możesz zadać sobie podobne pytanie (i prawdopodobnie to, o którym OP chciał wiedzieć):]}

Z określonego podzbioru wszystkich gałęzi, który jest najbliższym rodzicem gałęzi git?

Aby uprościć, rozważę "gałąź git", aby odnosić się do HEAD (tj. obecny oddział).

Wyobraźmy sobie, że mamy następujące gałęzie:]}
HEAD
important/a
important/b
spam/a
spam/b

Rozwiązania bazujące na filtrach git show-branch -a + mogą dawać, że najbliższym rodzicem HEAD jest spam/a, ale nam to nie zależy.

Jeśli chcemy wiedzieć, który z important/a i important/b jest najbliższym rodzicem HEAD, możemy uruchomić następujące polecenie:

for b in $(git branch -a -l "important/*"); do
    d1=$(git rev-list --first-parent ^${b} HEAD |wc -l);
    d2=$(git rev-list --first-parent ^HEAD ${b} |wc -l);
    echo "${b} ${d1} ${d2}";
done \
|sort -n -k2 -k3 \
|head -n1 \
|awk '{print $1}';

Co robi:

1.) $(git branch -a -l "important/*"): wyświetla listę wszystkich gałęzi z określonym wzorem ("important/*").

2.) d=$(git rev-list --first-parent ^${b} HEAD |wc -l);: dla każdego z tych branches ($b), Oblicz odległość ($d1) w liczbie commitów, od HEAD do najbliższego commita w $b (podobnie jak podczas obliczania odległości od punktu do linii). Możesz rozważyć odległość inaczej: możesz nie chcieć używać --first-parent, lub możesz chcieć odległość od końcówki do końcówki gałęzi ("${b}"...HEAD), ...

2.2) d2=$(git rev-list --first-parent ^HEAD ${b} |wc -l);: dla każdej z tych gałęzi ($b) Oblicz odległość ($d2) w liczbie commitów od wierzchołka gałęzi do najbliższy commit w HEAD. Użyjemy tej odległości do wyboru pomiędzy dwoma gałęziami, których odległość $d1 była równa.

3.) echo "${b} ${d1} ${d2}";: wyświetla nazwę każdej z gałęzi, a następnie odległości, aby móc je później sortować (najpierw $d1, a następnie $d2).

4.) |sort -n -k2 -k3: Sortuj poprzedni wynik, więc otrzymujemy posortowaną (według odległości) listę wszystkich gałęzi, a następnie ich odległości (oba).

5.) |head -n1: pierwszym wynikiem poprzedniego kroku będzie gałąź która ma mniejszą odległość, tj. najbliższą gałąź macierzystą. Więc po prostu odrzuć wszystkie inne gałęzie.

6.) |awk '{print $1}';: zależy nam tylko na nazwie gałęzi, a nie NA odległości, więc wyodrębnij pierwsze pole, które było nazwą rodzica. Tutaj jest! :)

 1
Author: alx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-24 11:57:01

Każdy, kto chce to zrobić w dzisiejszych czasach-aplikacja SourceTree firmy Atlassian pokazuje świetną wizualną reprezentację tego, jak twoje gałęzie odnoszą się do siebie, tj. gdzie zaczęły się i gdzie obecnie znajdują się w kolejności commitów (np. HEAD lub 4 commity z tyłu itp.).

 0
Author: jake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-05 02:20:30

Jeśli używasz drzewa źródeł, spójrz na szczegóły commita > Parents > wtedy zobaczysz numery commitów podkreślone (linki)

 0
Author: Mike6679,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-03 19:29:02

Alternatywa: git rev-list master | grep "$(git rev-list HEAD)" | head -1

Get The last commit that it ' s both my branch and master (or whatever branch you want to specific)

 0
Author: Alexander Woods,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-15 18:29:22

To nie działa dla mnie, gdy zrobiłem coś takiego develop > release-v1.0.0 > feature-foo, to przejść całą drogę Wstecz, aby rozwinąć, zauważ, że był rebase zaangażowany, Nie wiem, czy to jest komplikować mój problem...

Poniżej podano prawidłowy hash commit dla mnie

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
 0
Author: verdverm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-19 20:01:10
git log -2 --pretty=format:'%d' --abbrev-commit | tail -n 1 | sed 's/\s(//g; s/,/\n/g';

(pochodzenie / nazwa rodzica, nazwa rodzica)

git log -2 --pretty=format:'%d' --abbrev-commit | tail -n 1 | sed 's/\s(//g; s/,/\n/g';

Pochodzenie / nazwa rodzica

git log -2 --pretty=format:'%d' --abbrev-commit | tail -n 1 | sed 's/(.*,//g; s/)//';

Nazwa rodzica

 0
Author: Ivan Kuznetsov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-03 09:35:00

Git jest dostarczany z kilkoma klientami GUI, które pomagają ci to zwizualizować. Otwórz GitGUI i przejdź do menu Repository > Visualize All Branch History

 0
Author: Rod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-30 14:50:07