web-dev-qa-db-fra.com

Comment trouver le prochain commit dans git? (enfant/enfants de ref)

ref^ fait référence au commit avant ref, que diriez-vous d'obtenir le commit afterref?

Par exemple, si je git checkout 12345, comment puis-je extraire le prochain commit?

Merci.

PS Oui, git est un arbre de structure de pointeur de nœud DAG. Comment trouver le commit après celui-ci?

189
Schwern

Pour lister tous les commits, en commençant par celui en cours, puis par son enfant, etc.

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

où 894e8b4e93d8f3 est le premier commit que vous voulez afficher.

158
Tim Hunt

Le créateur de Hudson (maintenant Jenkins) Kohsuke Kawaguchi vient de paraître (novembre 2013):
kohsuke/git-children-of :

Étant donné un commit, trouvez les enfants immédiats de ce 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

Comme illustré par ce fil , dans un VCS basé sur l'historique représenté par un DAG (Directed Acyclic Graph) , il n'y a pas "un parent" ou "un enfant".

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

La commande des commits se fait par "topo-order" ou par "date-order" (voir livre GitPro )

Mais depuis Git1.6.0 , vous pouvez lister les enfants d’un commit.

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

Remarque: pour parent commits , vous avez le même problème, avec le suffixe ^ pour un paramètre de révision qui signifie le premier parent de cet objet de validation. ^<n> signifie le <n>th parent (i.e. rev^ est équivalent à rev^1).

Si vous êtes sur la branche foo et émettez "git merge bar", alors foo sera le premier parent.
I.e: Le premier parent est la branche sur laquelle vous étiez lorsque vous avez fusionné, et le second est la validation sur la branche dans laquelle vous avez fusionné.

30
VonC

ce que j'ai trouvé c'est

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

où je règle commit1 comme validation actuelle et commit2 à la tête actuelle. Cela me renvoie une liste de tous les commits qui construisent un chemin entre commit1 et commit2.

La dernière ligne de la sortie est l'enfant de commit1 (sur le chemin d'accès à commit2).

17
white_gecko

Je vois ce que tu veux dire. C'est frustrant d'avoir une syntaxe abondante pour passer aux commits précédents, mais aucune pour passer aux prochains. Dans une histoire complexe, le problème de "quel est le prochain commit" devient assez difficile, mais dans une fusion complexe, la même dureté émerge également avec les précédents "commits". Dans le cas simple, à l'intérieur d'une seule branche avec une histoire linéaire (même localement pour un nombre limité de commits), il serait agréable et judicieux d'avancer et de revenir en arrière.

Le vrai problème avec cela, cependant, est que les commits enfants ne sont pas référencés, il s’agit uniquement d’une liste à liens inversés. La recherche de l’enfant commis prend une recherche, ce qui n’est pas si mal, mais probablement pas quelque chose que git veut mettre dans la logique refspec.

En tout cas, je suis tombé sur cette question parce que je veux simplement avancer dans l’historique, commettez-vous à la fois, en faisant des tests, et parfois vous devez avancer et non pas en arrière. Eh bien, avec un peu plus de réflexion, je suis venu avec cette solution:

Choisissez un engagement avant votre destination. Cela pourrait probablement être une tête de branche. Si vous êtes à la branche ~ 10, "git checkout branch ~ 9" Puis "git checkout branch ~ 8" pour obtenir le suivant, Puis "git checkout branche ~ 7", etc.

Décrémenter le nombre devrait être très facile dans un script si vous en avez besoin. Beaucoup plus facile que d'analyser git rev-list.

7
vontrapp

Il n'y a pas de "prochain commit" unique. Comme l'historique dans Git est un DAG et non une ligne, de nombreux commits peuvent avoir un parent commun (branches) et les commits peuvent avoir plusieurs parents (fusions).

Si vous avez une branche en tête, vous pouvez consulter son journal et voir quelle liste de validation est présente dans la liste, comme parent.

6
Phil Miller

Deux réponses pratiques:

Un enfant

Basé sur @ la réponse de Michael , j'ai piraté l'alias child dans mon .gitconfig.

Cela fonctionne comme prévu dans le cas par défaut, et est également polyvalent.

# 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' -"

Par défaut, il donne à l'enfant de HEAD (sauf si un autre argument de commit-ish est donné) en suivant l'ascendance d'un pas vers la pointe de la branche courante (à moins qu'un autre commit-ish ne soit donné comme second argument).

Utilisez %h au lieu de %H si vous souhaitez utiliser la forme abrégée.

Plusieurs enfants

Avec un HEAD détaché (il n’ya pas de branche) ou pour avoir tous les enfants indépendamment des branches:

# 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' -"

Changez le $1 en $* pour imprimer tous les enfants.

Vous pouvez également changer --all en commise pour afficher uniquement les enfants qui sont les ancêtres de cette validation, autrement dit pour afficher uniquement les enfants "dans le sens de" la validation donnée. Cela peut vous aider à réduire la sortie de plusieurs enfants à un seul.

5
Tom Hale

J'ai essayé beaucoup de solutions différentes et aucune n'a fonctionné pour moi. Doit venir avec le mien.

trouver le prochain commit

function n() {
    git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}

trouver le commit précédent

function p() {
    git checkout HEAD^1
}
4
M K

Si vous n'avez pas à l'esprit une validation "de destination" particulière, mais souhaitez plutôt voir les validations enfants susceptibles de se trouver surtoute branche, vous pouvez utiliser cette commande:

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

Si vous voulez voir tous les enfantset les petits-enfants, vous devez utiliser rev-list --children de manière récursive, comme suit:

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

(La version qui donne seulement petits-enfants utiliserait une variable plus complexe sed et/ou cut.)

Enfin, vous pouvez insérer cela dans une commande log --graph pour voir l’arborescence, comme ceci:

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

J'ai cet alias dans ~/.gitconfig

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

Si les commits enfants sont tous sur une branche, vous pouvez utiliser gitk --all commit^.., où "commit" est quelque chose qui identifie la validation. Par exemple, si l'abréviation SHA-1 de la validation est c6661c5, tapez gitk --all c6661c5^..

Vous devrez probablement saisir le SHA-1 complet dans la cellule "SHA1 ID:" de gitk. Vous aurez besoin du SHA-1 complet, qui pour cet exemple peut être obtenu via git rev-parse c6661c5

Sinon, git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d' produira une ligne contenant tous les enfants de ce commit, que ce soit ou non une branche impliquée.

2
user339589

J'ai réussi à trouver le prochain enfant de la manière suivante:

git log --reverse --children -n1 HEAD (where 'n' is the number of children to show)
2
DevRQ

Ce post ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) montre une manière soignée Si vous le faites, vous pouvez créer une balise bien définie à la fin de votre pile de validation. Essentiellement git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`' où "demo-end" est la dernière balise. 

0
Alex Dresko

Chaque commit stocke un pointeur sur son parent (parents, en cas de fusion (standard) commit).

Donc, il n'y a aucun moyen de pointer sur un commit enfant (s'il en existe un) à partir du parent.

0
Lakshman Prasad