Reputation: 707
Below is a small example with Mercurial and similarly with Git.
I cannot understand how to make a hg update
with Git:
I have a small Mercurial setup with 4 commits - where I step back one commit
hg init
echo "1" > a.txt; hg commit -A -m "1. commit" a.txt
echo "2" >> a.txt; hg commit -m "2. commit" a.txt
echo "3" >> a.txt; hg commit -m "3. commit" a.txt
echo "4" >> a.txt; hg commit -m "4. commit" a.txt
hg update -r 3
thg # or hg view`
This gives this picture
Note that I see all four commit - i.e. both the pre-history and the following commit(s)
Let me try to do the same example using Git
git init
echo "1" > a.txt; git add a.txt; git commit -m "1. commit" a.txt
echo "2" >> a.txt; git commit -m "2. commit" a.txt
echo "3" >> a.txt; git commit -m "3. commit" a.txt
echo "4" >> a.txt; git commit -m "4. commit" a.txt # gives for me [master 57bb375]
Let me see the commits:
git log --graph --pretty=format:'%h -%d %s (%cr) <%an>'
* 57bb375 - (HEAD, master) 4. commit (14 minutes ago) <Peter Toft>
* 724a493 - 3. commit (14 minutes ago) <Peter Toft>
* bb38732 - 2. commit (14 minutes ago) <Peter Toft>
* 879c593 - 1. commit (15 minutes ago) <Peter Toft>
Good - four commits as expected. Let me go back one commit (similar as hg update)
git checkout 724a493
What about the git log now?
git log --graph --pretty=format:'%h -%d %s (%cr) <%an>'
* 724a493 - (HEAD) 3. commit (19 minutes ago) <Peter Toft>
* bb38732 - 2. commit (19 minutes ago) <Peter Toft>
* 879c593 - 1. commit (19 minutes ago) <Peter Toft>
gitk will also just show the first 3 commits?
So "git checkout" is NOT just similar to "hg update". Where are the following commit(s)?
Upvotes: 10
Views: 5281
Reputation: 73768
To put it simply, the 57bb375
commit did not go anywhere when you ran git checkout 724a493
. The behavior you're seeing is simply that git log
only shows commits that are ancestors of the checked out commit.
In Mercurial terms, git log
is the same as
$ hg log -r ::.
which means "show me commits that are ancestors of .
, i.e., the working copy parent revision". To get the equivalent of hg log
in Git, simply run
$ git log --all
This little difference is a key feature for Git since it allows you to pull in commits from lots of other repositories without seeing them by default. It is only if you checkout a branch (or a commit in your case) that you will see the commits you've downloaded into your repository.
Upvotes: 3
Reputation: 707
Another solution variant: Adding
[alias]
restore = "!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep ^D | cut -f 2); }; f"
then "git restore" will move me one commit backwards in time without requiring me to make an artificial branch.
If I want to return to the master branch
git checkout master
Upvotes: 0
Reputation: 4452
hg update -r 3
is giving you an automatic branch head to which you could continue committing. In git, checkout
takes you to the right commit, but doesn't give you a new branch head. If you want that you can say
git checkout -b new_branch_name 724a493
of course using whatever you like as the name. If you don't use -b
, as in your question, you get into the state of a detached HEAD ... which is exactly the difference between hg update -r 3
and git checkout 724a493
. Note the message Git prints when you do your checkout (from me running your example):
Note: checking out '2ffb5e0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at 2ffb5e0... 3. commit
Upvotes: 8