On Mon, 18 Apr 2005, Russell King wrote:
>
> Since this happened, I've been working out what state my tree is in,
> and I restored it back to a state where I had one dangling commit head,
> which was _my_ head.
For the future, if your tree gets messed up to the point where you say
"screw it" and just want to go back in time, you can do this (it's
equivalent to "undo" in BK speak):
git log | less -S
.. find which HEAD it was that you trusted..
In this case your HEAD before I merged with it was this one:
df4449813c900973841d0fa5a9e9bc7186956e1e
So to get back to that one, you can do
echo df4449813c900973841d0fa5a9e9bc7186956e1e > .git/HEAD
and now
cat-file commit $(cat .git/HEAD) | head -1
gives you
tree a43c4447b2edc9fb01a6369f10c1165de4494c88
so you can restore your checked-out state with
read-tree a43c4447b2edc9fb01a6369f10c1165de4494c88
checkout-cache -f -a
update-cache --refresh
and your tree should be valid again.
Now, to remove any bogus objects, you can then run my "git-prune-script"
(look at it carefully first to make sure you realize what you are doing).
NOTE NOTE NOTE! This will _revert_ everything you had done after the
"trusted" point. So you may not actually want to do this. Instead:
> It's very much like I somehow committed against the _parent_ of the
> head, rather than the head itself.
That's very common if you just forget to update your new ".git/HEAD" when
you do a commit.
Again, it's the tools that make it a bit too easy to mess up. The
"commit-tree" thing is supposed to really only be used from scripts (which
would do something like
result=$(commit-tree ...) && echo $result > .git/HEAD
but when doing things by hand, if you forget to update your HEAD, your
next commit will be done against the wrong head, and you get dangling
commits.
The good news is that this is not that hard to fix up. The _trees_ are all
correct, and the objects are all correct, so what you can do is just
generate a few new (proper) commit objects, with the right parents. Then
you can do the "git-prune-script" thing that will throw away the old
broken commits, since they won't be reachable from your new commits (even
though their _trees_ will be there and be the same).
So in this case:
b4a9a5114b3c6da131a832a8e2cd1941161eb348
+- e7905b2f22eb5d5308c9122b9c06c2d02473dd4f
+- dc90c0db0dd5214aca5304fd17ccd741031e5493 <-- extra dangling head
+- 488faba31f59c5960aabbb2a5877a0f2923937a3
you can do
cat-file commit dc90c0db0dd5214aca5304fd17ccd741031e5493
to remind you what your old tree and commit message was, and then just
re-commit that tree with the same message but with the proper parent:
commit-tree xxxx -p 488faba31f59c5960aabbb2a5877a0f2923937a3
and then you need to do the same thing for the other commits (which will
now need to be re-based to have the new commit-chain as their parents).
Then, when you fixed up the final one, remember to update .git/HEAD with
its commit ID, and now the prune-thing will get rid of the old dangling
commits that you just created new duplicates of.
Linus
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html