20

Is there a command that will let me checkout a commit based on its distance from the current commit instead of using commit IDs?

Use Case

Basically I am thinking of setting up a cron job type script to do the following on a build server:

  • Pull down the latest of a specific git branch (git pull dev).
  • Build it, run the tests.
  • If the pass percentage is lower than the last stored percentage:
    • Recursively go back a commit, build, run tests, until it finds the commit where the percentage changed.
    • Log the commits that introduced regressions.

I have a rough idea for how this would hinge together but it won't work unless I can go back one commit periodically.

If there is no specific command I suppose I could grep the commit log and take the first one each time?

I appreciate any ideas or help!

Unlike: How to undo last commit(s) in Git?

I want to go back "N" number of commits.

Community
  • 1
  • 1
chrispepper1989
  • 2,100
  • 2
  • 23
  • 48
  • Are you running the tests on a `staging/production` environment? – draxxxeus May 24 '13 at 16:11
  • 2
    @chrispepper1989 you should take a look at [the documentation for bisect](http://git-scm.com/docs/git-bisect), as [Peter pointed out](http://stackoverflow.com/a/16739578/456814), since you can use it to automate the process of finding the commit where regressions in tests occur. There's also [a section about it in the Pro Git book](http://git-scm.com/book/en/Git-Tools-Debugging-with-Git). –  May 25 '13 at 05:18
  • @TheShadow and gcbenison thank you so much for bringing me to the attention of git bisect, I will definitely use this! – chrispepper1989 May 29 '13 at 13:47
  • 1
    Possible duplicate of [How to undo last commit(s) in Git?](http://stackoverflow.com/questions/927358/how-to-undo-last-commits-in-git) – Jim Fell Feb 14 '17 at 18:54

2 Answers2

33
git checkout HEAD~N

will checkout the Nth commit before your current commit.

If you have merge commits in your history, you may be interested in

git checkout HEAD^N

which will checkout the Nth parent of a merge commit (most merge commits have 2 parents).

So, to always go back one commit following the first parent of any merge commits:

git checkout HEAD^1

You may also be interested in git bisect - Find by binary search the change that introduced a bug.

Peter Lundgren
  • 8,787
  • 2
  • 26
  • 21
  • 1
    Also, repeating `^` takes you back one each time, e.g. `HEAD^^^` is the same as `HEAD~3`. Docs are in `git help rev-parse` (which is used by many commands). – 13ren May 24 '13 at 16:29
  • 1
    `~` actually always follows first parents according to [the Git docs](http://git-scm.com/docs/gitrevisions.html): "A suffix `~` to a revision parameter means the commit object that is the th generation ancestor of the named commit object, following only the first parents." –  May 24 '13 at 16:44
  • 2
    The original poster should really take a look at automating [`git bisect`](http://git-scm.com/docs/git-bisect) actually. There's also [a section about it in the Pro Git book](http://git-scm.com/book/en/Git-Tools-Debugging-with-Git). –  May 25 '13 at 05:15
  • I would also like to point out that the `1` in `git checkout HEAD^1` is redundant, since `^` implies the first parent by default when no number is given. –  May 25 '13 at 05:26
  • this answer answers my original question and TheShadow added the icing on the cake with the link to the bisect command thanks!! – chrispepper1989 May 29 '13 at 13:48
  • Stackoverflow just told me this question has been viewed a lot, which is very humbling, I just wanted to use this chance to say *git bisect* is 100% what I should have used here and I believe i did go on to use it to great effect. It's a great tool to have in the belt of any dev :) you wont use it often, but when you do, its a lifesaver – chrispepper1989 Aug 08 '22 at 13:27
11

Iterating over each commit and running the tests could be really inefficient if the number of commits is much larger than the number of commits that introduce errors. There's no need to run the tests against every commit in the history, to find the one that introduced the error! You really should look at git bisect, particularly git bisect run.

The question indicates you want to find every commit that introduced an error since some point in history, not just the most recently introduced one. I don't think you can do that with one invocation of git bisect; you'll have to put it in a loop in a small script.

gcbenison
  • 11,723
  • 4
  • 44
  • 82
  • 1
    this is a great answer to my question, i had to give best answer to Peter as he answered my original question however git bisect is definitely a command i will use, thanks! – chrispepper1989 May 29 '13 at 13:49