14

How do I reference a commit ahead of HEAD?

For example, a commit that is 1 commit behind HEAD is HEAD~1.

How do I move the opposite direction, with respect to HEAD?

Basically, I did a git checkout HEAD~1 3 times. Now I want to move forward 1 commit, effectively undoing my last git checkout HEAD~1. How can I do this?

I understand that a branch of commits is like a singly linked list, with each commit only pointing to its parent. So if it unreasonable to traverse to a commit's child, I would like to know how to process forward between them.

Farhad
  • 12,178
  • 5
  • 32
  • 60
modulitos
  • 14,737
  • 16
  • 67
  • 110
  • There isn't currently a shorthand for referencing children ([gitrevisions(7)](https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html)). Related Q&A: [Referencing the child of a commit in Git](http://stackoverflow.com/questions/1761825/referencing-the-child-of-a-commit-in-git) If the commit is no longer being referenced (dangling, possible for `git-gc` to remove), you may be able to find it with [`git-reflog`](https://www.kernel.org/pub/software/scm/git/docs/git-reflog.html). – Jonathan Lonowski Mar 06 '16 at 06:54
  • Possible duplicate of [Undoing git reset?](http://stackoverflow.com/questions/2510276/undoing-git-reset) – Joe Mar 06 '16 at 10:25

4 Answers4

3

A commit can have unlimited children. If you want to see all the histories that trace back to a commit you can

git log --all --ancestry-path ^$commit

or just

git branch --contains $commit
git tag --contains $commit

to show their names.

with whatever display options you want. If you want to automate finding commits whose parent is a particular commit you could start with

child-commits() { 
        git rev-list --all --ancestry-path --parents ^$1^{} \
        | awk /$(git rev-parse $1^{})'/ {print $1}'
}

But if you just want to see where you've been, use

git reflog

to show what's affected your HEAD, and why.

jthill
  • 55,082
  • 5
  • 77
  • 137
2

Briefly:

git checkout $(git log --all --ancestry-path ^HEAD --format=format:%H | tail -n 1)

Explanation:

The git log command will give you the children (--all --ancestry-path) from where you currently are (^HEAD) printing only the hash (--format=format:%H). We then pipe that (|) to the tail command asking for only the last line, which should contain the hash of the child commit. (Piping to tail is platform dependant but will likely work on most Mac or Unix-like systems.)

Finally the git checkout $(...) part is simply running the other part in a subshell and getting back the hash of the child commit, then checking it out.

Caveat: if you have multiple child commits / lineages of commits, the order of traversal will be as per git log, which may (or may not) be what you expect.

Rachel K. Westmacott
  • 2,038
  • 20
  • 15
0

If your changes were pushed to remote you will be able to access the child, but not using HEAD as reference. But you can use git reflog to get history of all commits and checkout the required commit

Aditya Singh
  • 15,810
  • 15
  • 45
  • 67
0

Read this out about all the ways in which you can set up the new HEAD

How to move HEAD back to a previous location? (Detached head)

Basically you need to decide to which commit you want to switch to and simply checkout this commit in a various ways as explained in the above link.


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

This will checkout new branch pointing to the desired commit.
This command will checkout to a given commit.
At this point you can create a branch and start to work from this point on.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
#in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

You can always use the reflog as well

git reflog
git checkout HEAD@{...}

This will get you back to your desired commit

enter image description here


git reset HEAD --hard <commit_id>

"Move" your head back to the desired commit.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Note: (Since Git 2.7)
    you can also use the git rebase --no-autostash as well.

Here is a general schema of what can be done.

Community
  • 1
  • 1
CodeWizard
  • 128,036
  • 21
  • 144
  • 167