Come trovare il genitore più vicino a un ramo Git?


419

Diciamo che ho il seguente repository locale con un albero di commit come questo:

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

masterè mio questo è l'ultimo codice di rilascio stabile , developè mio questo è il 'prossimo' codice di rilascio ed featureè una nuova funzionalità in preparazionedevelop .

Quello che voglio essere in grado di fare sul mio repository remoto usando hook, è featurerifiutare le spinte a meno che il commit non fsia un discendente diretto di developHEAD. cioè l'albero di commit appare così perché la funzione è stata git rebaseattivata d.

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

Quindi è possibile:

  • Identificare il ramo padre di feature?
  • Identificare il commit nel ramo padre di cui fè discendente?

Da lì verificherei quale HEAD del ramo padre è, e fvedrei se il predecessore corrisponde al ramo padre HEAD, per determinare se la funzione deve essere rivista.


questa domanda dovrebbe essere riformulata per trovare il genitore di un genitore.
Tim Boland,

Risposte:


348

Supponendo che il repository remoto abbia una copia del ramo di sviluppo (la descrizione iniziale lo descrive in un repository locale, ma sembra che esista anche nel telecomando), dovresti essere in grado di ottenere ciò che penso tu voglia, ma l'approccio è un po 'diverso da quello che hai immaginato.

La storia di Git si basa su un DAG di commit. Le filiali (e "ref" in generale) sono solo etichette temporanee che indicano impegni specifici nel DAG di commit in continua crescita. In quanto tale, la relazione tra filiali può variare nel tempo, ma la relazione tra commit non lo fa.

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

Sembra che bazsia basato su (una vecchia versione di) bar? E se cancellassimo bar?

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

Ora sembra che bazsia basato su foo. Ma la discendenza di baznon è cambiata, abbiamo semplicemente rimosso un'etichetta (e il conseguente commit penzolante). E se aggiungessimo una nuova etichetta su 4?

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

Ora sembra che bazsia basato su quux. Tuttavia, la discendenza non è cambiata, sono cambiate solo le etichette.

Se, tuttavia, ci chiedessimo "è commettere 6un discendente di commettere 3?" (supponendo 3che 6siano nomi di commit SHA-1 completi), la risposta sarebbe "sì", indipendentemente dal fatto barche quuxsiano presenti le etichette e .

Quindi, potresti porre domande come "il commit push è un discendente della punta corrente del ramo di sviluppo ?", Ma non puoi chiedere in modo affidabile "qual è il ramo parent del commit push?".

Una domanda per lo più affidabile che sembra avvicinarsi a ciò che vuoi è:

Per tutti gli antenati del commit spinto (escluso l'attuale suggerimento di sviluppo e i suoi antenati), che hanno l'attuale suggerimento di sviluppo come genitore:

  • esiste almeno un tale commit?
  • sono tutti commit di questo tipo?

Che potrebbe essere implementato come:

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

Questo coprirà parte di ciò che vuoi limitato, ma forse non tutto.

Per riferimento, ecco una cronologia di esempio estesa:

    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

Il codice di cui sopra potrebbe essere usato per respingere He Saccettando H', J, K, o N, ma sarebbe anche accettare Le P(che coinvolgerà le unioni, ma non unire la punta di sviluppo ).

Per rifiutare anche Le P, è possibile modificare la domanda e porre

Per tutti gli antenati del commit spinto (escluso l'attuale suggerimento di sviluppo e i suoi antenati):

  • ci sono impegni con due genitori?
  • in caso contrario, almeno uno di questi commit ha l'attuale suggerimento di sviluppare il suo (unico) genitore?
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

Ottengo questo: git: fatal: argomento ambiguo '...': sia revisione che nome file. qual è l'intenzione dei punti tripli?
Jack Ukleja,

1
@Schneider Sono abbastanza sicuro che '...' sia destinato a essere un segnaposto in questo esempio: se lo sostituisci con lo SHA del commit stai provando a eseguire questo controllo contro (diciamo, HEAD del ramo al momento sei attivo), tutto funziona perfettamente.
Daniel Brady,

Grazie per questa risposta elaborata! È super utile. Voglio creare un hook simile, ma non voglio codificare il nome del ramo di sviluppo. Significato Voglio un gancio per impedire il rebase a un ramo diverso dal ramo padre. Se capisco bene la tua risposta (sono nuovo su bash e cose del genere), questo non è coperto dalla tua risposta, giusto? C'è un modo per fare questo?
Kemeia,

Sei disposto a rispondere a una domanda correlata? Non sono riuscito a far funzionare il tuo codice su un repository REMOTE. Ecco il link alla domanda di follow-up su come adattare il vostro approccio al lavoro con un repository remoto: stackoverflow.com/questions/49619492/...
CodeMed

Questo non ha funzionato per me quando l'avrei fatto develop > release > feature, mi sarei sviluppato di nuovo e richiede la conoscenza del genitore. La soluzione al mio problema era stackoverflow.com/a/56673640/2366390
verdverm

241

Una riformulazione

Un altro modo per formulare la domanda è "Qual è il commit più vicino che risiede su un ramo diverso da quello corrente e quale ramo è quello?"

Una soluzione

Puoi trovarlo con un po 'di magia da riga di comando

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

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

Ecco come funziona:

  1. Visualizza una cronologia testuale di tutti i commit, incluse le filiali remote.
  2. Gli antenati dell'attuale commit sono indicati da una stella. Filtra tutto il resto.
  3. Ignora tutti i commit nel ramo corrente.
  4. Il primo risultato sarà il ramo dell'antenato più vicino. Ignora gli altri risultati.
  5. I nomi delle filiali sono visualizzati [tra parentesi]. Ignora tutto al di fuori delle parentesi e delle parentesi.
  6. A volte il nome del ramo includerà un ~ # o ^ # per indicare quanti commit sono tra il commit a cui si fa riferimento e il suggerimento del ramo. Non ci interessa. Ignorali.

E il risultato

In esecuzione il codice sopra

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

Ti darà developse lo esegui da H e masterse lo esegui da I.

Il codice è disponibile come sintesi


24
Rimosso un backtick finale che ha causato un errore. Quando eseguo questo comando, ricevo una grande quantità di avvisi, lamentandomi per ogni filiale che dicecannot handle more than 25 refs
Jon L.

1
@JoeChrysler pensi che si può fare una linea invece di 2, e possibilmente farlo funzionare su Mac, come acknon è disponibile su Mac (qualcuno ha proposto di sostituire ackcon grep)
nonopolarity

53
Siamo spiacenti, è sbagliato. Ecco quello corretto che ha funzionato per me:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot,

15
@droidbot Nice, ma ha bisogno di riordinare le tubazioni per evitare la rimozione di refs quando grep -v cattura il messaggio di commit o il nome del tuo ramo fa parte di un altro nome di ramo. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
gaal

3
@OlegAbrazhaev Non so se hai mai avuto risposta alla tua domanda. usando l'alias git di: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"funziona per me
mduttondev

111

Puoi anche provare:

git log --graph --decorate

5
git log --graph --decorate --simplify-by-decorationdove --graphè facoltativo.
Na13-c,

1
git log --graph --decorate --simplify-by-decoration --oneline
anishtain4

106

genitore git

Puoi semplicemente eseguire il comando

git parent

per trovare il genitore del ramo, se aggiungi la risposta di @Joe Chrysler come alias git . Semplificherà l'utilizzo.

Apri il file gitconfig che si trova su "~/.gitconfig"usando qualsiasi editor di testo. (Per Linux). E per Windows il percorso ".gitconfig" si trova generalmente inc:\users\your-user\.gitconfig

vim  ~/.gitconfig

Aggiungi il seguente comando alias nel file:

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

Salva ed esci dall'editor.

Esegui il comando git parent

Questo è tutto!


5
Questa è un'ottima soluzione Sarebbe utile aggiungere anche alcuni output di esempio per essere certi dei risultati previsti. Quando l'ho eseguito, ho ricevuto alcuni avvertimenti prima dell'ultima riga che credo fosse il nome del ramo principale.
temp

4
Funziona come un fascino! Per gli utenti di Windows, il .gitconfig si trova generalmente in c: \ users \ your-user \ .gitconfig
zion

12
Ottenere cannot handle more than 25 refsun'eccezione.
Shajin,

qualcuno può modificarlo per gestire l'avviso? @ttemple, puoi?
NIKHIL CM

@NIKHILCM funziona come un campione. Ma ho una domanda qui se il genitore indica da dove ha creato il ramo o qualcos'altro?
Hariprasath,

52

Ho una soluzione al tuo problema generale (determinare se featurediscende dalla punta di develop), ma non funziona usando il metodo che hai delineato.

È possibile utilizzare git branch --containsper elencare tutti i rami discendenti dalla punta di develop, quindi utilizzare grepper assicurarsi che featuresia tra questi.

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

Se è tra questi, stamperà " feature"sullo standard output e avrà un codice di ritorno di 0. Altrimenti, non stamperà nulla e avrà un codice di ritorno di 1.


1
Funziona, ma va notato che può richiedere molto tempo su un repository che ha molti riferimenti. Ciò lo rende un po 'meno che ideale per l'esecuzione, ad esempio un hook di pre-ricezione.
ebneter,

Stavo cercando il ramo, lo chiameremo <branch>, dove mi sono esibito: git checkout -b <branch-2>da ... QUESTA è la risposta! Non c'è bisogno di grep, davvero. git branch --contains <branch>
Poopy McFartnoise,

44

Questo funziona bene per me.

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

Risposte di cortesia da: @droidbot e @Jistanidiot


Sì, ma a volte ti prende "tubo rotto" da grep.
Vladislav Rastrusny,

1
*non è una regex corretta da passare a grep. Dovrebbe usare grep -F '*'o grep '\*'invece. Buona soluzione altrimenti.
arielf

Non ho ricevuto output.
Sandip Subedi,

funziona per me ....
roottraveller,

11

Poiché nessuna delle risposte sopra ha funzionato sul nostro repository, voglio condividere la mia strada, usando le ultime fusioni in git log:

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

Inseriscilo in uno script chiamato git-last-merges, che accetta anche un nome di ramo come argomento (anziché il ramo corrente) e altri git logargomenti

Dall'output, possiamo rilevare manualmente i rami principali in base alle proprie convenzioni di diramazione e al numero di fusioni da ciascun ramo.

EDIT: Se usi git rebasespesso rami secondari (e le fusioni avanzano spesso spesso, quindi non ci sono troppi commit di unione), questa risposta non funzionerà bene, quindi ho scritto uno script per contare i commit in avanti (normale e unione) e dietro commit (non dovrebbe esserci alcuna fusione dietro nel ramo padre) su tutti i rami rispetto al ramo corrente. Esegui questo script e fammi sapere se funziona per te o no

#!/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

Grazie. Anche se questo potrebbe non funzionare molto bene se lo usi rebasespesso (e le fusioni vengono fast-forwardeseguite spesso). Modificherò la mia risposta se avessi trovato una soluzione migliore.
Saeedgnu,

1
Il solo? risposta finora che ha funzionato in modo ragionevole per me nel caso in cui l'attuale ramo sia padrone. La maggior parte delle altre soluzioni ha dato un risultato casuale (e chiaramente errato) in questo caso limite in cui non ci sono filiali principali effettive.
arielf

Questa è l'unica risposta che ha funzionato per me. Per ottenere il primo genitore anziché un elenco dei primi 10 è possibile utilizzare questo: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
lots0logs

10

Una soluzione

La soluzione basata sugit show-branch non ha funzionato del tutto per me (vedi sotto), quindi l'ho combinata con quella basata sugit log e ho finito con questo:

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

Limitazioni e avvertenze

  • HEAD può essere staccato (molti strumenti CI lo fanno per assicurarsi di creare un commit corretto in un determinato ramo), ma il ramo di origine e il ramo locale devono essere entrambi alla pari o "sopra" l'attuale HEAD.
  • Non devono esserci tag nel modo (presumo; non ho testato lo script su commit con un tag tra ramo figlio e genitore)
  • la sceneggiatura si basa sul fatto che "HEAD" è sempre elencato come prima decorazione dal logcomando
  • in esecuzione lo script su masteredevelop risultati (per lo più) in<SHA> Initial commit

I risultati

 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

Nonostante l'esistenza di una filiale locale (ad es. origin/topicÈ presente solo dal momento che il commit è Ostato estratto direttamente dal proprio SHA), lo script dovrebbe stampare come segue:

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

* - oppure mastersedevelop gli commit fossero in cima alla HEAD del master (~ il master sarebbe in grado di avanzare rapidamente per lo sviluppo)


Perché non ha funzionato per il settore spettacoli per me

La soluzione basata sugit show-branch si è rivelata inaffidabile per me nelle seguenti situazioni:

  • TESTA staccata - compresa la custodia staccata significa sostituiregrep '\*' \ "grep"! ' \ - e questo è solo l'inizio di tutti i problemi
  • in esecuzione lo script su masteredevelop risultati indevelop e `` rispettivamente
  • i rami sulmaster ramo ( hotfix/rami) finiscono con developcome genitore poiché il loro mastergenitore di ramo più vicino è stato contrassegnato con !invece che *per un motivo.

2
L'unica risposta che ha funzionato - come alias 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

Ricorda che, come descritto in "Git: Trovare da quale ramo proviene un commit" , non puoi facilmente individuare il ramo in cui è stato fatto quel commit (i rami possono essere rinominati, spostati, cancellati ...), anche se git branch --contains <commit>è un inizio.

  • Puoi tornare da commit a commit finché git branch --contains <commit>non vengono elencati il featureramo e il ramo elenco develop,
  • confrontare il commit di SHA1 con /refs/heads/develop

Se i due commit coincidono, sei a posto (ciò significherebbe che il featureramo ha la sua origine alla testa di develop).


6

La magia della riga di comando di JoeChrysler può essere semplificata. Ecco la logica di Joe - per brevità ho introdotto un parametro chiamato cur_branchal posto della sostituzione del comando `git rev-parse --abbrev-ref HEAD`in entrambe le versioni; che può essere inizializzato in questo modo:

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

Quindi, ecco la pipeline di 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

Possiamo realizzare la stessa cosa di tutti e cinque i singoli filtri di comando in un awkcomando relativamente semplice :

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

Questo si scompone così:

-F'[]^~[]' 

dividere la linea in campi a ], ^, ~, e [caratteri.

/\*/                      

Trova le righe che contengono un asterisco

&& !/'"$cur_branch"'/

... ma non l'attuale nome del ramo

{ print $2;               

Quando trovi una tale linea, stampa il suo secondo campo (cioè la parte tra la prima e la seconda occorrenza dei nostri caratteri di separazione dei campi). Per nomi di rami semplici, sarà proprio quello che c'è tra parentesi; per i ref con relativi salti, sarà solo il nome senza il modificatore. Quindi il nostro set di separatori di campo gestisce l'intento di entrambi i sedcomandi.

  exit }

Quindi esci immediatamente. Ciò significa che elabora sempre e solo la prima riga corrispondente, quindi non è necessario reindirizzare l'output head -n 1.


3
Si noti che alcuni rami possono mancare nell'output a causa di troppi riferimenti. Sono invece mostrati come avvertimenti su stderr.
Zitrax,

5

Ecco un'implementazione di PowerShell della soluzione di Mark Reed:

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

5

Non sto dicendo che questo è un buon modo per risolvere questo problema, tuttavia questo sembra funzionare per me.

git branch --contains $(cat .git/ORIG_HEAD) Il problema è che cat'ing un file sta sbirciando nel funzionamento interno di git, quindi questo non è necessariamente compatibile con il passato (o retrocompatibile).


3

Implementazione multipiattaforma con 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}" />

2

@Mark Reed: dovresti aggiungere che la riga di commit non dovrebbe contenere solo un asterisco, ma iniziare con un asterisco! Altrimenti i messaggi di commit che contengono un asterisco sono inclusi anche nelle righe corrispondenti. Quindi dovrebbe essere:

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

o la versione lunga:

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

Raggiunge gli stessi fini della risposta di Mark Reed, ma utilizza un approccio molto più sicuro che non si comporta in modo errato in una serie di scenari:

  1. L'ultimo commit del ramo padre è un'unione, che mostra la colonna - non*
  2. Il messaggio di commit contiene il nome del ramo
  3. Il messaggio di commit contiene *

0

Chiunque voglia farlo in questi giorni - l'applicazione SourceTree di Atlassian ti mostra un'ottima rappresentazione visiva di come i tuoi rami si relazionano l'uno con l'altro, cioè dove sono iniziati e dove siedono attualmente nell'ordine di commit (ad esempio HEAD o 4 commit dietro, ecc.) .


0

Se usi l'albero dei sorgenti guarda i dettagli del tuo commit> Genitori> vedrai i numeri di commit sottolineati (link)


0

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

Ottieni l'ultimo commit che è sia il mio ramo che master(o qualunque ramo tu voglia specificare)


0

Questo non ha funzionato per me quando avevo fatto qualcosa del genere develop > release-v1.0.0 > feature-foo, sarebbe tornato indietro fino a svilupparsi, nota che c'era un rebase coinvolto, non sono sicuro se questo sta aggravando il mio problema ...

Quanto segue ha dato l'hash di commit corretto per me

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.