Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referencing the child of a commit in Git

Tags:

git

If you want to move the HEAD to the parent of the current HEAD, that's easy:

git reset --hard HEAD^ 

But is there any simple way to do the exact opposite of this operation, that is, set the head to the current head's first child commit?

Right now, I use gitk as a workaround (alt-tab, up-arrow, alt-tab, middle-click), but I would like a more elegant solution, one that can also be used when gitk is not available.

like image 678
AttishOculus Avatar asked Nov 19 '09 08:11

AttishOculus


People also ask

How do I refer to a specific commit in git?

If you want to go to a particular commit of a git repository with submodules you can use 2 git commands: reset or checkout. You will also need to synchronise the submodules after the working directory has been altered as that doesn't happen automatically.

What is the parent of a git commit?

The parent commit is the commit this current commit is based on. Usually: When you git commit normally, the current commit becomes the parent commit of the new commit that's introduced by the command.

How do you jump to a commit?

To jump back to a previous commit, first find the commit's hash using git log . This places you at commit 789abcd . You can now make new commits on top of this old commit without affecting the branch your head is on. Any changes can be made into a proper branch using either branch or checkout -b .

Can a commit have no parent?

Create a new orphan branch, named <new_branch>, started from <start_point> and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.


2 Answers

Very probably not the fastest possible solution, but it does what I need:

 #!/bin/bash  REV=$1  if [[ -z "$REV" ]]; then     echo "Usage: git-get-child  []"     exit fi  HASH=$(git rev-parse $REV)  NUM=$2  if [[ -z "$NUM" ]]; then     NUM=1 fi  git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/\([^ ]*\) .*$/\\1/p" 

The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:

SHA1_commit SHA1_parent1 SHA1_parent2 etc.

The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.

like image 96
AttishOculus Avatar answered Sep 22 '22 12:09

AttishOculus


The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:

branches=$(git branch --contains $commit| grep -v '[*] ('| sed -e 's+^..++') 

will determine the set of branches that $commit is an ancestor of. With a modern git, at least version 2.21+, this should do the same without the need for sed (untested):

branches=$(git branch --format='%(refname:short)' --contains $commit| grep -v '[*] (') 

Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.

like image 35
Rainer Blome Avatar answered Sep 22 '22 12:09

Rainer Blome