git: Are these dangling commits?
Asked Answered
H

2

10

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:

  1. What could have caused this situation (i.e. branch #1 getting detached)?

  2. How can I detect whether there are similar issues in other repositories? (without having to know the hashes of detached commits such as #3)

Commits detached from branch

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.

Heterotrophic answered 2/1, 2016 at 10:2 Comment(0)
P
3
  1. as you said; this is caused by using git push --force
  2. 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...

Postman answered 5/1, 2016 at 7:24 Comment(2)
The trick is the fact that they are reachable via a tag! This did answer my question. Your script also worked; it correctly showed all the commits that were not on a branch and a few more as well.Heterotrophic
By the way, git fsck reports a lot of dangling tags as well. What could cause tags to dangle?Heterotrophic
A
5

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.

Adinaadine answered 4/1, 2016 at 0:53 Comment(4)
git fsck --full didn't produce any output either. However, I ran it on a fresh clone of the problematic repo (i.e. without any branch, other than the master, being checked out). Does fsck works only on the checked out branches? If so, can it detect dangling commits as they don't belong to any branch?Heterotrophic
git fsck check you r git repository regardless any branch. it verify all your commitsAdinaadine
Irrespective of whether branches are locally checked out or not? In the fresh clone there aren't any loose objects; only a couple of pack files. Can that be the reason for not getting any errors with fsck?Heterotrophic
Even after checking out a couple of branches, including the problematic branch, still there are no errors reported on git fsck --full. But when supplied with a hash, it produced the five dangling commits listed in the question. I tried about three different hashes, and fsck gives the same set of dangling commits as output.Heterotrophic
P
3
  1. as you said; this is caused by using git push --force
  2. 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...

Postman answered 5/1, 2016 at 7:24 Comment(2)
The trick is the fact that they are reachable via a tag! This did answer my question. Your script also worked; it correctly showed all the commits that were not on a branch and a few more as well.Heterotrophic
By the way, git fsck reports a lot of dangling tags as well. What could cause tags to dangle?Heterotrophic

© 2022 - 2024 — McMap. All rights reserved.