问题
Suppose a_branch
is an existing branch that points to a different commit than the one HEAD
points to (HEAD
might point to a commit directly or via some branch
).
Are the following commands equivalent?
git checkout a_branch
and
git symbolic-ref HEAD ref/heads/a_branch
git reset --hard a_branch
See also this related post.
回答1:
No, they're not, if you have staged or dirty changes before you run the commands.
If you modify a pre-existing file before running git checkout
, the modification will persist after HEAD
is moved. This is true whether the changes are staged or dirty.
The same does not hold when running git reset --hard
. The modifications, staged or dirty, will be destroyed when you run git reset --hard
.
回答2:
I also wondered, what git checkout
(and git branch
) really means in "plumbing" commands. Therefore, I tried one case, where I created a new branch, as it was only for learning the basics. To make sure, I don't miss anything, I started from scratch:
Create a folder "Test" with one file "test.txt" and write
"Great content" into that file.
Using chapter 10 from the git book, I investigated the following sequence:
git init
git add .
git commit -m "Init"
- EITHER porcelain commands:
git branch b1
git checkout b1
- OR plumbing commands:
git symbolic-ref HEAD
git update-ref refs/heads/b1 $(git rev-parse HEAD)
The result: The two coincide!
The details. I will use the following commands to check the status:
Used commands from Git bash:
find .git/refs -type f
find all files in .git/refsgit symbolic-ref HEAD
points the symbolic HEAD reference, the same ascat .git/HEAD
git rev-parse HEAD
get the history (Commits, objects?) reachable by HEADgit rev-list --objects --all
View all commit-objectsgit cat-file -p refs/heads/master
View the file content.
If there were different branches with no common history, one has to usegit rev-list --objects --no-walk $(git fsck --unreachable | grep '^unreachable commit' | cut -d' ' -f3)
git reflog
shows one commit and the HEAD history (just one commit) Git porcelain commandsgit branch -av
Show all branches with hash and message (Also displays remotes if there are any!).
In the following, the commands are only shown if they result is something non-empty or it has changed since the last step.
Initialize Git repo
git init # creates empty .git/ folder. HEAD exists but without history.
No objects in .git/objects. Folders /info and /pack are empty.
.git/refs/ is empty
Stage changes
git add .
find .git/refs -type f # One object in c1/ created:
git cat-file -p c15479631b40176f3b09b7bc74ac5e189190e991 # yields "great content"
git cat-file -t c15479631b40176f3b09b7bc74ac5e189190e991 # yields "blob"
Thus, one object in refs/objects/
was created
Commit changes
git commit -m "Init"
find .git/refs -type f # refs/heads/master created. Not empty. So have a look:
git symbolic-ref HEAD # refs/heads/master
git cat-file -p refs/heads/master # The full commit information including tree, author, commiter and commit message
git rev-parse HEAD # The hash to which HEAD points
git reflog # shows the HEAD history (just one commit)
# View all commit-objects. Everything is reachable by the commit:
git rev-list --objects --all
git cat-file -p $(git rev-parse HEAD) # Commit Hash changes with time. -t instead of -p yields "commit"
git cat-file -p 69b13879c229e1cc35f270db248910e5a828dc65 # -t yields tree
git cat-file -p c15479631b40176f3b09b7bc74ac5e189190e991 # -t yields blob
git branch -av
master branch with hash from git rev-parse HEAD
created
* master 7845459 Init
Create branch
git update-ref refs/heads/b1 $(git rev-parse HEAD)
# refs/heads/master still there. refs/heads/b1 created. So have a look:
find .git/refs -type f
git symbolic-ref HEAD # Still at ref/heads/master
git cat-file -p refs/heads/b1 # The same result as from "git cat-file -p refs/heads/master"
git branch -av
b1 exists but not checked out:
b1 7845459 Init
* master 7845459 Init
Checkout b1, i.e update HEAD
git symbolic-ref HEAD refs/heads/b1
git symbolic-ref HEAD # now at refs/heads/b1 => b1 checked out! Cross-check:
git branch -av
b1 checked out:
* b1 7845459 Init
master 7845459 Init
I hope, this is helpful.
来源:https://stackoverflow.com/questions/43376142/checkout-reset-symbolic-ref