问题
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_branchgit 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 initgit add .git commit -m "Init"- EITHER porcelain commands:
git branch b1git checkout b1
- OR plumbing commands:
git symbolic-ref HEADgit 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 ffind all files in .git/refsgit symbolic-ref HEADpoints the symbolic HEAD reference, the same ascat .git/HEADgit rev-parse HEADget the history (Commits, objects?) reachable by HEADgit rev-list --objects --allView all commit-objectsgit cat-file -p refs/heads/masterView 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 reflogshows one commit and the HEAD history (just one commit) Git porcelain commandsgit branch -avShow 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