Domanda Come trovo il prossimo commit in git? (bambino / figli di riferimento)


ref^ si riferisce al commit prima ref, che dire ottenere il commit dopo  ref?

Ad esempio, se io git checkout 12345 come controllo il prossimo commit?

Grazie.

PS Sì, git è un puntatore del nodo DAG struct tree qualunque. Come trovo il commit dopo questo?


179
2018-02-15 02:04


origine


risposte:


Per elencare tutti i commit, a partire da quello corrente, e quindi i suoi figli, e così via - in pratica git log standard, ma andando in senso contrario, usa qualcosa di simile

git log --reverse --ancestry-path 894e8b4e93d8f3^..master

dove 894e8b4e93d8f3 è il primo commit che vuoi mostrare.


150
2018-03-26 10:07



Il creatore di Hudson (ora Jenkins) Kohsuke Kawaguchi appena pubblicato (novembre 2013):
kohsuke / git-children-of:

Dato un commit, trova i figli immediati di quel commit.

#!/bin/bash -e
# given a commit, find immediate children of that commit.
for arg in "$@"; do
  for commit in $(git rev-parse $arg^0); do
    for child in $(git log --format='%H %P' --all | grep -F " $commit" | cut -f1 -d' '); do
      git describe $child
    done
  done
done

Come illustrato da questo thread, in un VCS basato sulla storia rappresentato da a DAG (Diretto grafico aciclico), non c'è "un genitore" o "un bambino".

        C1 -> C2 -> C3
      /               \
A -> B                  E -> F
      \               /
        D1 -> D2 ----/

L'ordine di commit è fatto da "ordine topografico" o "data-ordine" (vedi Libro GitPro)

Ma da allora Git1.6.0, puoi elencare i figli di un commit.

git rev-list --children
git log --children

Nota: per il genitore si impegna, hai lo stesso problema, con il suffisso ^ a un parametro di revisione che indica il primo genitore di quell'oggetto commit. ^<n> significa il <n>il genitore (cioè rev^  è equivalente a rev^1).

Se sei nel ramo foo e problema "git merge bar" poi foo sarà il primo genitore.
I.e: il primo genitore è il ramo in cui ti trovavi quando ti sei unito e il secondo è il commit sul ramo in cui ti sei fuso.


30
2018-02-15 07:23



quello che ho trovato è

git rev-list --ancestry-path commit1..commit2

dove ho impostato commit1 come il commit corrente e commit2 alla testa attuale. Questo mi restituisce un elenco di tutti i commit che creano un percorso tra commit1 e commit2.

L'ultima riga dell'output è figlio di commit1 (sul percorso di commit2).


13
2018-05-19 21:51



Non esiste un unico "prossimo commit". Poiché la cronologia di Git è un DAG e non una riga, molti commit possono avere un genitore comune (rami) e i commit possono avere più di un genitore (unione).

Se hai in mente un ramo particolare, puoi guardare il suo log e vedere quali liste di commit sono presenti come padre.


6
2018-02-15 02:37



So cosa vuoi dire. È frustrante avere una sintassi abbondante per passare a commit precedenti, ma nessuno per passare a quelli successivi. In una storia complessa, il problema di "qual è il prossimo commit" diventa piuttosto difficile, ma poi nella fusione complessa emerge la stessa durezza con commit "precedenti". Nel caso semplice, all'interno di un singolo ramo con una cronologia lineare (anche solo localmente per un numero limitato di commit) sarebbe bello e avere senso andare avanti e indietro.

Il vero problema con questo, tuttavia, è che i bambini commessi non sono referenziati, è solo una lista collegata all'indietro. Trovare il commit del bambino richiede una ricerca, che non è male, ma probabilmente non è qualcosa che git vuole mettere nella logica refspec.

Ad ogni modo, mi sono imbattuto in questa domanda perché voglio semplicemente fare un passo avanti nella storia, un impegno alla volta, fare dei test e, a volte, devi fare un passo avanti e non tornare indietro. Bene, con un po 'di più ho pensato a questa soluzione:

Scegli un impegno prima di dove sei. Questo potrebbe probabilmente essere un capo di branca. Se sei al ramo ~ 10, quindi "git checkout branch ~ 9" quindi "git checkout branch ~ 8" per ottenere il successivo dopo, quindi "git checkout branch ~ 7" e così via.

Il decremento del numero dovrebbe essere veramente facile in uno script se ne hai bisogno. Molto più facile di parsing git rev-list.


6
2018-02-27 04:50



Nel caso in cui non si abbia una particolare "destinazione" in mente, ma invece si desidera vedere i commit bambino che potrebbero essere attivi qualunque ramo, è possibile utilizzare questo comando:

git rev-list --children --all | grep ^${COMMIT}

Se vuoi vedere tutti i bambini e nipoti, devi usare rev-list --children in modo ricorsivo, in questo modo:

git rev-list --children --all | \
egrep ^\($(git rev-list --children --all | \
           grep ^${COMMIT} | \
           sed 's/ /|/g')\)

(La versione che dà solo i nipoti userebbero un più complesso sed e / o cut.)

Infine, puoi nutrirlo in a log --graph comando per vedere la struttura ad albero, in questo modo:

git log --graph --oneline --decorate \
\^${COMMIT}^@ \
$(git rev-list --children --all | \
  egrep ^\($(git rev-list --children --all | \
             grep ^${COMMIT} | \
             sed 's/ /|/g')\))

4
2017-12-01 21:36



Due risposte pratiche:

Un bambino

Basato su @ La risposta di Michael, Ho hackerato il child alias nel mio .gitconfig.

Funziona come previsto nel caso predefinito ed è anche versatile.

# Get the child commit of the current commit.
# Use $1 instead of 'HEAD' if given. Use $2 instead of curent branch if given.
child = "!bash -c 'git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:\"$(git rev-parse --abbrev-ref HEAD)\"} | head -1' -"

Il valore predefinito è dare al figlio di HEAD (a meno che non venga fornito un altro argomento di commit-ish) seguendo l'ascendenza di un passo verso la punta del ramo corrente (a meno che un altro commit-ish sia dato come secondo argomento).

Uso %h invece di %H se vuoi il breve modulo di hash.

Più bambini

Con una testa staccata (non c'è ramo) o per ottenere tutti i bambini indipendentemente dai rami:

# For the current (or specified) commit-ish, get the all children, print the first child 
children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $1' -"

Cambiare il $1 a $* per stampare tutti i bambini


4
2017-09-19 06:11



Ho questo alias in ~/.gitconfig

first-child = "!f() { git log  --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; }; f"

3
2018-05-03 05:36