Search code examples
gitshallow-clone

Remove graft mark in git when history becomes available


I'm experimenting with git shallow clones and wonder if there is any possibility to "ungraft" a commit if I happen to fetch the parent of an already existing commit.

Let's say I have a full repo with three commits looking like this (letters indicating their checksums):

A--B--C

I then want a shallow clone of only commit C, and perform the following actions:

git init
git remote add origin url_to_my_repo
git fetch --depth=1 C
git checkout FETCH_HEAD

This leaves me with a shallow clone of the origin repo, where only commit C is available. The commit is marked as grafted, indicating the broken history. Let's say I now also fetch commit B in the same way:

git fetch --depth=1 B
git checkout FETCH_HEAD

Now it is getting interesting. I have two commits that are both marked grafted. Recalling that each commit records its parent checksum, which can be successfully verified using e.g. git cat-file -p C, Git actually has all necessary information to replace the grafted mark of commit C with the real history which in fact is available.

In essence, I want the same outcome as if I would checkout commit C with a depth of 2 in the first place.

I've read this excellent explanation regarding grafted commits, however it requires me to do a manual intervention. I'm sure there must be a command to tell git to check all grafted commits if the grafted mark can be removed, e.g. with git fsck.

Any ideas?


Solution

  • After reading up a bit on the documentation of shallow concept, I started to play around with the shallow-file located in the .git-folder. Essentially it is a list of all commits that are grafted. Removing a commit hash in the file successfully "ungrafts" that very commit (i.e. the graft marker is removed, and history viewed correctly in git log).

    One should be somewhat careful when directly editing anything within the .git-folder, but this at least points in the right direction on how to ungraft commits without perform git fetch --unshallow.

    Edit:

    I created a python script for this very purpose and recently published it on GitHub, should anyone be interested: https://github.com/chrillof/git-ungraft