Como encontrar o pai mais próximo de um ramo Git?

419

Digamos que eu tenho o seguinte repositório local com uma árvore de confirmação como esta:

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

masteré meu, este é o código de lançamento estável mais recente , developé meu é o 'próximo' código de lançamento e featureé um novo recurso que está sendo preparadodevelop .

O que eu quero poder fazer no meu repo remoto usando ganchos é que os impulsos featuresejam recusados, a menos que o commit fseja um descendente direto do developHEAD. ou seja, a aparência de árvores cometer assim porque recurso tem sido git rebaseem d.

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

Então é possível:

  • Identifique o ramo pai de feature?
  • Identifique a confirmação no ramo pai da qual fé descendente?

A partir daí, eu verificaria o que é HEAD da ramificação pai e veria se o fpredecessor corresponde à HEAD da ramificação pai, para determinar se o recurso precisa ser reformulado.

Peter Farmer
fonte
essa pergunta deve ser reformulada para encontrar o pai ou mãe.
Tim Boland

Respostas:

348

Supondo que o repositório remoto tenha uma cópia do ramo de desenvolvimento (sua descrição inicial o descreve em um repositório local, mas parece que também existe no remoto), você deve conseguir o que eu acho que deseja, mas a abordagem é um pouco diferente do que você imaginou.

A história do Git é baseada em um DAG de confirmações. Ramos (e “refs” em geral) são apenas rótulos transitórios que apontam para confirmações específicas no DAG de confirmação em crescimento contínuo. Como tal, o relacionamento entre ramificações pode variar ao longo do tempo, mas o relacionamento entre confirmações não.

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

Parece que bazé baseado em (uma versão antiga do) bar? Mas e se excluirmos bar?

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

Agora parece que bazé baseado foo. Mas a ancestralidade de baznão mudou, apenas removemos um rótulo (e o commit dangling resultante). E se adicionarmos um novo rótulo em 4?

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

Agora parece que bazé baseado quux. Ainda assim, a ancestralidade não mudou, apenas os rótulos mudaram.

Se, no entanto, perguntássemos "é comprometer 6um descendente de confirmar 3?" (assumindo 3e 6com nomes completos de confirmação do SHA-1), a resposta seria "sim", independentemente de os rótulos bare quuxestarem presentes.

Portanto, você pode fazer perguntas como "o push enviado é descendente da ponta atual do ramo de desenvolvimento ?", Mas não é possível perguntar com segurança "qual é o ramo pai do commit enviado?".

Uma pergunta principalmente confiável que parece se aproximar do que você deseja é:

Para todos os ancestrais do commit enviado (excluindo a dica atual de desenvolvimento e seus ancestrais), que têm a dica atual de desenvolvimento como pai:

  • existe pelo menos um desses commit?
  • são todos esses commit confirmados monoparentais?

O que poderia ser implementado como:

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

Isso cobrirá parte do que você deseja restringir, mas talvez nem tudo.

Para referência, aqui está um histórico de exemplo estendido:

    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

O código acima poderia ser usado para rejeitar He Sao aceitar H', J, K, ou N, mas seria também aceitar Le P(eles envolvem fusões, mas eles não se fundem a ponta de desenvolver ).

Para também rejeitar Le P, você pode alterar a pergunta e fazer

Para todos os ancestrais do commit enviado (excluindo a dica atual de develop e seus ancestrais):

  • há algum comprometimento com dois pais?
  • caso contrário, pelo menos um desses commit tem a dica atual de desenvolver seu (único) pai?
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
Chris Johnsen
fonte
Entendi: git: fatal: argumento ambíguo '...': revisão e nome do arquivo. qual é a intenção dos pontos triplos?
Jack Ukleja
1
@Schneider Tenho certeza de que o '...' deve ser um espaço reservado neste exemplo: se você substituí-lo pelo SHA do commit, você está tentando executar essa verificação (por exemplo, o HEAD do ramo você está atualmente), tudo funciona muito bem.
Daniel Brady
Obrigado por esta resposta elaborada! É super útil. Quero criar um gancho semelhante, mas não quero codificar o nome do ramo de desenvolvimento. Ou seja, eu quero um gancho para impedir o rebase de um ramo que não seja o ramo pai. Se eu entendo bem a sua resposta (eu sou novo no bash e outras coisas), isso não é abordado na sua resposta, certo? Existe uma maneira de fazer isso?
Kemeia
Você está disposto a responder a uma pergunta relacionada? Não consegui que seu código funcionasse em um repositório REMOTE. Aqui está o link para a pergunta de acompanhamento sobre como adaptar sua abordagem para trabalhar com um repositório REMOTE: stackoverflow.com/questions/49619492/…
CodeMed
Isso não funcionou para mim quando eu tinha develop > release > feature, eu voltaria a desenvolver e requer conhecer os pais. A solução para o meu problema era stackoverflow.com/a/56673640/2366390
verdverm
241

Uma reformulação

Outra maneira de formular a pergunta é "Qual é o commit mais próximo que reside em uma ramificação que não seja a ramificação atual e qual ramificação é essa?"

Uma solução

Você pode encontrá-lo com um pouco de magia da linha de comando

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

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

Veja como funciona:

  1. Exiba um histórico textual de todas as confirmações, incluindo ramificações remotas.
  2. Os ancestrais do commit atual são indicados por uma estrela. Filtrar todo o resto.
  3. Ignore todas as confirmações na ramificação atual.
  4. O primeiro resultado será o ramo ancestral mais próximo. Ignore os outros resultados.
  5. Os nomes das filiais são exibidos [entre colchetes]. Ignore tudo fora dos colchetes e colchetes.
  6. Às vezes, o nome da ramificação inclui um ~ # ou ^ # para indicar quantas confirmações existem entre a confirmação referenciada e a dica da ramificação. Nós não nos importamos. Ignore-os.

E o resultado

Executando o código acima em

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

Dará a você developse você executá-lo de H e masterse você executá-lo de I.

O código está disponível como uma essência

Joe Chrysler
fonte
24
Removido um backtick final que causava erro. Ao executar este comando, porém, eu obter uma grande quantidade de avisos, queixando-se cada ramo dizendocannot handle more than 25 refs
Jon L.
1
@JoeChrysler que você acha que pode torná-lo uma linha em vez de 2, e possivelmente fazê-lo funcionar no Mac como acknão está disponível no Mac (alguém sugeriu a substituição ackcom grep)
nonopolarity
53
Desculpe, isso é errado. Aqui é o correto que funcionou para mim:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot
15
@droidbot Agradável, mas precisa de reordenar a tubulação para evitar a remoção de referências quando a mensagem grep -v catch commit ou o nome do seu ramo faz parte de outro nome do ramo. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
gaal
3
@OlegAbrazhaev Não sei se você já teve sua pergunta respondida. usando o alias git de: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"funciona para mim
mduttondev
111

Você também pode tentar:

git log --graph --decorate
rcde0
fonte
5
git log --graph --decorate --simplify-by-decorationonde --graphé opcional.
Na13-c 12/02/19
1
git log --graph --decorate --simplify-by-decoration --oneline
anishtain4
106

pai git

Você pode simplesmente executar o comando

git parent

para encontrar o pai da ramificação, se você adicionar a resposta de @Joe Chrysler como um alias do git . Isso simplificará o uso.

Abra o arquivo gitconfig localizado em "~/.gitconfig"usando qualquer editor de texto. (Para linux). E para Windows, o caminho ".gitconfig" geralmente está localizado emc:\users\your-user\.gitconfig

vim  ~/.gitconfig

Adicione o seguinte comando de alias no arquivo:

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

Salve e saia do editor.

Execute o comando git parent

É isso aí!

NIKHIL CM
fonte
5
Esta é uma otima soluçao. Seria útil também adicionar uma amostra de saída para garantir os resultados esperados. Quando o executei, recebi alguns avisos antes da última linha, que acredito ser o nome do ramo pai.
ttemple 21/09
4
Funciona como um encanto! Para usuários do Windows, o .gitconfig geralmente está localizado em c: \ users \ your-user \ .gitconfig
zion
12
Obtendo cannot handle more than 25 refsexceção.
shajin 18/02/19
alguém pode editar isso para lidar com o aviso? @ttemple, você pode?
NIKHIL CM
@NIKHILCM funciona como um campeão. Mas eu tenho uma pergunta aqui, se o pai indica de onde o ramo foi criado ou algo mais?
Hariprasath 11/12/19
52

Eu tenho uma solução para o seu problema geral (determine se featureé descendente da ponta do develop), mas ele não funciona usando o método descrito.

Você pode usar git branch --containspara listar todos os ramos descendentes da ponta do e develop, em seguida, usar greppara garantir que featureesteja entre eles.

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

Se estiver entre eles, imprimirá " feature"na saída padrão e terá um código de retorno 0. Caso contrário, não imprimirá nada e terá um código de retorno 1.

Daniel Stutzbach
fonte
1
Isso funciona, mas deve-se notar que pode demorar muito tempo em um repositório com muitas refs. Isso o torna um pouco menos do que ideal para rodar, por exemplo, em um gancho de pré-recebimento.
ebneter 19/01/19
Eu estava olhando para o ramo, vamos chamá-lo <branch>, onde i realizada: git checkout -b <branch-2>a partir de ... Esta é a resposta! Não há necessidade de grep, realmente. git branch --contains <branch>
Poopy McFartnoise 17/07/19
44

Isso está funcionando bem para mim.

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

Respostas de cortesia de: @droidbot e @Jistanidiot

Murali Mopuru
fonte
Sim, mas às vezes você recebe "cachimbo quebrado" do grep.
Vladislav Rastrusny
1
*não é uma regex adequada para passar ao grep. Deve usar grep -F '*'ou em grep '\*'vez disso. Boa solução caso contrário.
Arielf 14/05/19
Não tenho saída.
Sandip Subedi
funciona para mim ....
roottraveller 14/02
11

Como nenhuma das respostas acima funcionou em nosso repositório, quero compartilhar do meu jeito, usando as últimas mesclagens em git log:

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

Coloque-o em um script chamado git-last-merges, que também aceita um nome de filial como argumento (em vez da filial atual), além de outros git logargumentos

A partir da saída, podemos detectar manualmente os ramos principais com base em convenções de ramificação próprias e no número de mesclagens de cada ramo.

EDIT: Se você usa git rebasefrequentemente em ramos secundários (e as mesclagens são encaminhadas com frequência, para que não haja muitos commit de mesclagem), essa resposta não funcionará bem, então escrevi um script para contar antecipadamente os commits (normal e mesclado) , e confirmações por trás (não deve haver nenhuma fusão por trás na ramificação pai) em todas as ramificações em comparação com a ramificação atual. Basta executar este script e deixe-me saber se funciona para você ou não

#!/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
saeedgnu
fonte
Obrigado. Embora isso possa não funcionar muito bem se você usar com rebasefrequência (e as mesclagens são fast-forwardfeitas com frequência). Vou editar minha resposta se encontrar uma solução melhor.
Saeedgnu
1
O único? responder até agora que funcionou sensatamente para mim no caso em que o ramo atual é o mestre. A maioria das outras soluções deu um resultado aleatório (e claramente incorreto) nesse caso reconhecidamente extremo, onde não há ramificações principais reais.
Arielf
Esta é a única resposta que funcionou para mim. Para obter o primeiro pai em vez de uma lista dos 10 primeiros, você pode usá-lo: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
lots0logs
10

Uma solução

A solução baseada nagit show-branch não muito trabalho para mim (veja abaixo), para que eu tenha isso combinado com a base emgit log e acabamos com isto:

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

Limitações e advertências

  • O HEAD pode ser desanexado (muitas ferramentas de IC o fazem para garantir a criação correta de commit em um determinado ramo), mas o ramo de origem e o ramo local precisam estar no mesmo nível ou "acima" do HEAD atual.
  • Não deve haver tags no caminho (presumo; não testei o script em confirmações com uma tag entre filho e ramo pai)
  • o script depende do fato de "HEAD" estar sempre listado como a primeira decoração pelo logcomando
  • executar o script em masteredevelop resultados (principalmente) em<SHA> Initial commit

Os resultados

 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

Apesar da existência da ramificação local (por exemplo, apenas origin/topicestá presente desde que o commit Ofoi retirado diretamente pelo seu SHA), o script deve ser impresso da seguinte maneira:

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

* - ou masterse developos commits estiverem no topo da HEAD do mestre (~ o ​​mestre seria rápido em desenvolver)


Por que o show-branch não funcionou para mim

A solução baseada emgit show-branch provou não ser confiável para mim nas seguintes situações:

  • CABEÇA desanexada - incluindo o caso da cabeça desanexada significa substituir grep '\*' \por `grep '!' \ - e isso é apenas o começo de todos os problemas
  • executar o script em masteredevelop resultados em develope `` respectivamente
  • ramificações emmaster ramificações ( hotfix/ramificações) acabam com o developpai como pai, já que o pai mais próximo masterfoi marcado com e !não *por um motivo.
Matt Stuvysant
fonte
2
Única resposta que funcionou - como um alias do git:"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Ian Kemp
8

Lembre-se de que, conforme descrito em "Git: Localizando a ramificação de uma confirmação" , você não pode identificar facilmente a ramificação em que a confirmação foi feita (as ramificações podem ser renomeadas, movidas, excluídas ...), mesmo que isso git branch --contains <commit>seja um começo.

  • Você pode voltar de commit para commit até git branch --contains <commit>não listar o featurebranch e list developbranch,
  • compare esse commit SHA1 com /refs/heads/develop

Se os dois confirmarem a correspondência de ID, você estará pronto (isso significaria que a featureramificação tem sua origem no HEAD de develop).

VonC
fonte
6

A mágica da linha de comando de JoeChrysler pode ser simplificada. Aqui está a lógica de Joe - por uma questão de brevidade, introduzi um parâmetro nomeado cur_branchno lugar da substituição de comando `git rev-parse --abbrev-ref HEAD`nas duas versões; que podem ser inicializados da seguinte maneira:

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

Então, aqui está o pipeline de 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

Podemos realizar a mesma coisa que todos os cinco filtros de comando individuais em um awkcomando relativamente simples :

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

Isso se divide assim:

-F'[]^~[]' 

dividir a linha em campos em ], ^, ~e [caracteres.

/\*/                      

Encontre linhas que contenham um asterisco

&& !/'"$cur_branch"'/

... mas não o nome do ramo atual

{ print $2;               

Quando você encontrar essa linha, imprima seu segundo campo (ou seja, a parte entre a primeira e a segunda ocorrências de nossos caracteres separadores de campo). Para nomes simples de ramificações, será exatamente o que está entre colchetes; para refs com saltos relativos, será apenas o nome sem o modificador. Portanto, nosso conjunto de separadores de campo lida com a intenção de ambos os sedcomandos.

  exit }

Então saia imediatamente. Isso significa que ele apenas processa a primeira linha correspondente, portanto não precisamos canalizar a saída head -n 1.

Mark Reed
fonte
3
Observe que algumas ramificações podem estar ausentes na saída devido a muitas refs. Eles são mostrados como avisos no stderr.
Zitrax 31/03/16
5

Aqui está uma implementação do PowerShell da solução de Mark Reed:

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

Não estou dizendo que essa é uma boa maneira de resolver esse problema, no entanto, isso parece funcionar para mim.

git branch --contains $(cat .git/ORIG_HEAD) A questão é que criar um arquivo está espreitando o funcionamento interno do git, portanto, isso não é necessariamente compatível com versões anteriores (ou com versões anteriores).

user1529413
fonte
3

Implementação de plataforma cruzada com 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}" />
ENargit
fonte
2

@ Mark Reed: Você deve adicionar que a linha de confirmação não deve conter apenas um asterisco, mas começar com um asterisco! Caso contrário, as mensagens de confirmação que contêm um asterisco também serão incluídas nas linhas correspondentes. Então deve ser:

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

ou a versão longa:

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`
ladiko
fonte
2
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/[\^~].*//'

Atinge os mesmos fins que a resposta de Mark Reed, mas usa uma abordagem muito mais segura que não se comporta mal em vários cenários:

  1. A última confirmação do ramo pai é uma mesclagem, fazendo a coluna - não mostrar*
  2. A mensagem de confirmação contém o nome da ramificação
  3. A mensagem de confirmação contém *
Haoyang Feng
fonte
0

Qualquer pessoa que queira fazer isso atualmente - o aplicativo SourceTree da Atlassian mostra uma ótima representação visual de como seus ramos se relacionam, por exemplo, onde eles começaram e onde estão atualmente na ordem de confirmação (por exemplo, HEAD ou 4 confirma atrás, etc.) .

Jake
fonte
0

Se você usar a Árvore de fontes, veja os detalhes de confirmação> Pais> e verá os números de confirmação sublinhados (links)

Mike6679
fonte
0

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

Obter o último commit que é meu ramo e master(ou qualquer ramo que você deseja especificar)

Alexander Woods
fonte
0

Isso não funcionou para mim quando eu tinha feito algo como develop > release-v1.0.0 > feature-foo: voltaria a se desenvolver, observe que houve uma recuperação, não tenho certeza se isso está agravando meu problema ...

O seguinte deu o hash de confirmação correto para mim

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
verdverm
fonte