How do I move forward and backward between commits in git?

Git

Git Problem Overview


I am doing a git bisect and after arriving to the problematic commit, I am now trying to get a step forward/backward to make sure I am in the right one.

I know of HEAD^ to go backwards in history but is there another shortcut to get me forward (towards a specific commit in the future) like so:

A - B - C(HEAD) - D - E - F

I know that my target is F and I want to move from C to D.


NOTE: this is not a duplicate of https://stackoverflow.com/q/2121230/146272, my question is slightly different and is not answered there

Git Solutions


Solution 1 - Git

I believe you can do:

git reset HEAD@{1}

To go one commit forward in time. To go forward multiple commits, use HEAD@{2}, HEAD@{3}, etc.

Solution 2 - Git

I've experimented a bit and this seems to do the trick to navigate forwards (edit: it works well only when you have a linear history without merge commits):

git checkout $(git rev-list --topo-order HEAD..towards | tail -1)

where towards is a SHA1 of the commit or a tag.

Explanation:

  • the command inside $() means: get all the commits between current HEAD and towards commit (excluding HEAD), and sort them in the precedence order (like in git log by default -- instead of the chronological order which is weirdly the default for rev-list), and then take the last one (tail), i.e. the one we want to go to.
  • this is evaluated in the subshell, and passed to git checkout to perform a checkout.

You can define a function accessible as a parameter-expecting alias in your .profile file to navigate forward towards the particular commit:

# Go forward in Git commit hierarchy, towards particular commit 
# Usage:
#  gofwd v1.2.7
# Does nothing when the parameter is not specified.
gofwd() {
  git checkout $(git rev-list --topo-order HEAD.."$*" | tail -1)
}

# Go back in Git commit hierarchy
# Usage: 
#  goback
alias goback='git checkout HEAD~'

Solution 3 - Git

All you need to get clear, not detached head state is to reset, not checkout.

git reset HEAD@{1}

Solution 4 - Git

This is what I'm using to navigate back and forth.

moving to next commit

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

moving to previous commit

function p() {
    git checkout HEAD^1
}

Solution 5 - Git

Say F is the latest commit on trunk (insert your own branch name here) ... you can refer to it as trunk~0 (or just trunk), E as trunk~1, D as trunk~2 etc.

Take a look in your reflog for yet more ways to name commits.

Solution 6 - Git

Traversing backward is trivial since you are moving down the tree, and there's always one way to go

  function git_down
        git checkout HEAD^
  end

When traversing forward you are moving up the tree, so you need to be explicit which branch you are targeting:

  function git_up 
        git log --reverse --pretty=%H $argv | grep -A 1 (git rev-parse HEAD) | tail -n1 | xargs git checkout
  end

Usage: git down, git up <branch-name>

Solution 7 - Git

If you want to see ahead, you can do this trick, as Git doesn't have strict command for it.

git log --reverse COMMIT_HASH..
Example

List of log history hashes:

A
B
C -> put this
D

using command git log --reverse C.., in output you will see B and A.

Solution 8 - Git

I just did a test on this. say for example you are in master branch Then do:

git checkout HEAD@{3}

So head gets detached, and you can then try it again to go to any other commit:

git checkout HEAD@{4}

Once you are done looking around, you can go back to your original state just by checking out to that branch. In my example: master branch

git checkout master

If you don't want to go to original state, and want so keep one of the commits as your head and continue from there, then you need to branch out from there. for example after "git checkout HEAD@{4}" , you can issue

git checkout -b MyNewBranch

Solution 9 - Git

Probably not the nicest way but you can use git log to view the list of commits and then use git checkout [sha1 of D] to move to D.

Solution 10 - Git

As a workaround, you can just return to HEAD with

git checkout <branch>

And then move to the commit you'd like to, with

git checkout HEAD~<offset>

Solution 11 - Git

If you are using vs code then Git history is an awesome plugin where you can efficiently see commits and check their contents in the editor itself. check out the link

Solution 12 - Git

branchName=master; commitInOrder=1; git checkout $(git log --pretty=%H "${branchName}" | tac | head -n "${commitInOrder}" | tail -n 1)

where:

branchName equals branch name

commitInOrder equals a commit in order from very first commit in the selected branch (so 1 is the very first commit, 2 is second commit in branch, etc.)

Solution 13 - Git

To GUI and vscode users I would recommend using the extension git graph

enter image description here

Solution 14 - Git

I would use git-reflog and git-reset.

It is not the same case as you run git-bisect, but suppose you git-reset to commit C and want to move it back to commit F.

At the point, git-reflog looks like this:

$ git reflog show
4444444 (HEAD -> main) HEAD@{0}: reset: moving to 4444444
1111111 HEAD@{1}: commit: F
2222222 HEAD@{2}: commit: E
3333333 HEAD@{3}: commit: D
4444444 (HEAD -> main) HEAD@{4}: commit: C
5555555 HEAD@{5}: commit: B
6666666 HEAD@{6}: commit: A

Then, you can run git-reset to go back to any commit by specifying SHA1 hash or offset number from HEAD.

In your case, run git-reset as follows:

$ git reset 1111111

or

$ git reset HEAD@{1}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKostasView Question on Stackoverflow
Solution 1 - Gitw0utertView Answer on Stackoverflow
Solution 2 - Gitjakub.gView Answer on Stackoverflow
Solution 3 - Gitd3dayView Answer on Stackoverflow
Solution 4 - GitM KView Answer on Stackoverflow
Solution 5 - GitUselessView Answer on Stackoverflow
Solution 6 - GitDziamidView Answer on Stackoverflow
Solution 7 - GitdimpiaxView Answer on Stackoverflow
Solution 8 - Gituser1322977View Answer on Stackoverflow
Solution 9 - Gitbb-generationView Answer on Stackoverflow
Solution 10 - GitPatrizio BertoniView Answer on Stackoverflow
Solution 11 - GitRahil AhmadView Answer on Stackoverflow
Solution 12 - GitguestView Answer on Stackoverflow
Solution 13 - GitNorfeldtView Answer on Stackoverflow
Solution 14 - Gitys64View Answer on Stackoverflow