2010-03-14 13 views
33

Background: utilizzo un sistema di build automatizzato che accetta un hash git come input, oltre al nome del ramo su cui esiste l'hash e lo costruisce. Tuttavia, il sistema di compilazione utilizza solo l'hash per verificare il codice e crearlo: memorizza semplicemente il nome del ramo, come indicato, nei metadati del DB di build.Come posso determinare se esiste un determinato hash git su una data diramazione?

Sono preoccupato per gli sviluppatori che forniscono accidentalmente il nome del ramo sbagliato quando prenderà il via una build, causando confusione quando le persone sono alla ricerca attraverso la storia di costruzione.

Quindi, come posso confermare, prima di passare il nome dell'hash e del ramo al sistema di generazione, che l'hash dato in effetti proviene dal ramo specificato?

+3

perché hai bisogno del nome del ramo? sembra un'informazione inutile al sistema di compilazione. E non vedo davvero come sarebbe utile a uno sviluppatore che legge i log di costruzione. – hasen

+0

Avresti bisogno del nome del ramo nel caso in cui il tuo flusso di lavoro abbia, non so, un ramo di sviluppo e master utilizzato per la distribuzione e vuoi sapere se i commit sono entrati in un particolare? A proposito, per favore accetta la vera risposta. –

+0

@Pinko Penso che la risposta selezionata dovrebbe essere [questa] (https://stackoverflow.com/a/2444924/161278). Dal momento che ha molti più voti e molto più semplice grazie all'uso della funzionalità git nativa. –

risposta

10

Hmm, questo uso di un nome del ramo sembra pesce. Come nella risposta di Dustin, potrebbero esserci più rami che contengono un commit. Perché uno di questi nomi di rami è migliore di un altro per questo scopo?


Se si interessa solo di un ramo specifico, è possibile calcolare la "base di unione" tra il ramo e il commit.

Negli schemi che seguono, il commit costruire è C, la punta del ramo dichiarato è T, e la base di unione è apposta la M sopra di esso.

  • Se M uguale C uguale T, poi la la impegnarsi a costruire è la punta del ramo rivendicato.

       M 
           ↓ 
    o--o--o--o--o--x branch # x is both C and T 
    
  • Se M uguale C, poi la punta del ramo dichiarato è un discendente del impegnarsi a costruire.

     M 
         ↓ 
    o--o--C--o--o--T branch 
    
  • Se M uguale T, quindi il commit di costruire è un discendente della punta del ramo rivendicato.

     M 
         ↓ 
    o--o--T   branch 
         \ 
         o--o--C 
    
  • Se M uguale a qualcosa d'altro, poi C è un discendente di qualche antenato di T.

     M 
         ↓ 
    o--o--o--o--o--T branch 
         \ 
         o--o--C 
    
  • Se non c'è M, quindi il commit di costruire non è correlato al ramo rivendicato.

    o--o--o--o--o--T branch 
    
    o--o--o--o--C 
    

È possibile effettuare questo controllo in questo modo:

#!/bin/sh 

# Usage: is-ancestor-of <branch> <commit> 

if test $# -ne 2; then 
    echo "$0"': invalid arguments' 
    exit 128 
fi 
claimed_branch="$1" 
commit="$2" 

merge_base="$(git merge-base "$commit" "$claimed_branch")" && 
    test -n "$merge_base" && 
    test "$merge_base" = "$(git rev-parse --verify "$commit")" && 
    exit 0 

echo "$commit is not an ancestor of $claimed_branch" 1>&2 
exit 1 

Lo script precedente in realtà non richiedono, o verificare che l'argomento 'ramo' è un ramo (potrebbe essere qualsiasi Commitee ish). Per controllare che qualcosa è in realtà un ramo, si potrebbe usare qualcosa di simile:

#!/bin/sh 

# Usage: is-branch <branch> 

if test $# -ne 1; then 
    echo "$0"': invalid arguments' 
    exit 128 
fi 
branch="$1" 

# check various branch hierarchies, adjust as needed 
git show-ref --verify refs/heads/"$branch" || 
git show-ref --verify refs/remotes/"$branch" || { 
    echo "not a branch name: $branch" 1>&2 
    exit 1 
} 

Così li si potrebbe usare insieme per verificare che qualcosa è un ramo e che un certo commit è in quel ramo:

is-branch "$claimed_branch" && is-ancestor-of "$claimed_branch" "$commit_to_build" 
+0

Molto interessante. +1 – VonC

+2

Soluzione più semplice @ http://stackoverflow.com/a/2444924/292408 –

+6

Perché diamine faresti questo quando git ha una soluzione integrata migliore? Perché mai è stata accettata questa risposta ridicolmente convulsa quando non è chiaramente la migliore? Ho perso tempo a setacciarlo, invece di scorrere verso il basso fino alla risposta che dovrebbe essere in cima. Wow ... –

1

Una possibile non-soluzione sarebbe quello di analizzare il risultato di:

$ git reflog show myBranch 

e vedere se il hash è in esso.

C:\Prog\Git\tests\rep\main>git reflog show patches 
786a190 [email protected]{0}: rebase finished: refs/heads/patches onto 74630b983db476c323b1d3f6771e57484551240e 
8448d0f [email protected]{1}: master~1: updating HEAD 
74630b9 [email protected]{2}: commit: test2 
1e73e36 [email protected]{3}: branch: Created from master 

io continuo questo come una risposta comunitaria Wiki per ricordare Igor Zevaka e commenti Chris Johnsen s':

Vorrei che il lavoro dopo un clone?
Assicurati che il tuo reflog inizi dopo aver clonato un telecomando. Quindi se un ramo aveva un commit prima del clone, non comparirebbe nel reflog.

Ci sono anche problemi con push, rebases, fetches (per i rami di "remote tracking") e pull (sia di tipo merge che di rebase) dove solo il nuovo suggerimento di punta termina il reflog.
Anche reflogs sono disabilitati di default nei repository nudo (la destinazione più comune per spinte).
Inoltre, se “barare” è un problema, è solo una questione di modifica di un file di testo per aggiungere o eliminare le voci reflog, ma è una prova più grande per alterare il grafico storia stessa.

+0

Questo funzionerebbe dopo un clone? Abbastanza sicuro che il tuo reflog inizi dopo aver clonato un telecomando. Quindi se un ramo aveva un commit prima del clone, non comparirebbe nel reflog. –

+0

Giusto, @Igor Zevaka. Ci sono anche problemi con push e rebases (dove solo il nuovo suggerimento del tip finisce nel reflog). Anche i reflog sono disabilitati di default nei repository nudi (la destinazione più comune per i push). Inoltre, se "barare" è un problema, è solo questione di modificare un file di testo per aggiungere o eliminare voci di reflog, ma è un calvario più grande per alterare il grafico della storia stesso. –

114

Si può chiedere direttamente git branch che si dirama contengono il commit in questione:

% git branch -a --contains 4f08c85ad 
* master 
    remotes/origin/bug_872 
    remotes/origin/bug_898 
    remotes/origin/master 
+5

Rimuovi l'opzione '-a' da elencare dal proprio ramo locale solo – ismailsunni

+0

È possibile utilizzare un ramo specifico invece di' -a' ad es. 'Il ramo $ git si sviluppa - contiene 4f08c85ad' –

Problemi correlati