问题
Given at the end is an extracted screenshot from a SourceTree branch tree view (there is a gap in the middle of the screenshot)
In that, #1
points to the line which used to be branch 1.7.6.14.X
and #2
points to the current status of the same branch.
The commit referred to by #3
and the preceding 8 commits on that line were previously attached to branch 1.7.6.14.X
. Then another developer supposedly checked out the same branch and did the fix pointed to by #4
. This #4
commit has removed the former 9 commits from branch 1.7.6.14.X
and left them dangling.
As a result, the branch 1.7.6.14.X
now starts from the original branching point instead of just extending from commit #3
.
Running git fsck
with --unreachable
, --dangling
etc doesn't give any errors. I tried --lost-found
as well.
However, git fsck <hash of commit #3>
produces five dangling commits and a whole bunch of dangling tags:
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3148/3148), done.
dangling commit ec213...
dangling commit ab82a...
dangling commit 7d262...
dangling commit a6f06...
dangling commit 6674a...
I have two questions:
What could have caused this situation (i.e. branch
#1
getting detached)?How can I detect whether there are similar issues in other repositories? (without having to know the hashes of detached commits such as
#3
)
Update:
We found the answer to question (1). The situation was caused by a force push, to the central bare repo, by a developer who had an older snapshot of the branch.
回答1:
- as you said; this is caused by using
git push --force
- Since all your commits are attainable with a tag; git will never say that hey are dangling, since they are not. They will never be lost nor cleaned up since a tag refers to them.
As to how to find these (for lack of a better word) dangling commits; I didn't find anything purely git, but I came up with a small script that allows detecting them. There might be a way to make this more performant, but is does the trick:
for sha in $(git log --all --pretty=format:"%H")
do
if [ -z "$(git branch --contains $sha)" ]
then
echo "commit not on a branch: $sha"
fi
done
note I know that the test -z ""
isn't very clean, but the return value of git branch
is always 0...
回答2:
Here is a post Linus Torvalds:
Linus describes what dangling objects are, when they are left behind, and how to view their relationship with branch heads in gitk
What could have caused this situation (i.e. branch #1 getting detached)?
Dangling data is data which is stored in the git repository but is un reachable.
Meaning that you have (added or committed) content which is not accessible in your repository, (no commit or branch is having or pointing to this content)
So the answer is yes, all the commits on branch #1 are not accessible from any commits beside branch #1.
How can I detect whether there are similar issues in other repositories?
(without having to know the hashes of detached commits such as #3)
git fsck --full
This command will check all the dangling content in your repository
There can be 2 kind of dangling content in your repository:
Dangling blob
Change(s) that made it to the staging area/index (once you do git add
git calculated the SHA-1 and starting to track the content) but never got committed.
Dangling commit
Commit(s) that isn't linked to any branch or tag either directly or by any of its ascendants.
来源:https://stackoverflow.com/questions/34564658/git-are-these-dangling-commits