Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving a git subtree into different repository

I try to move a directory and all its history from repository to another repository.

Extracting the complete history of the directory is easy with git subtree split.

This creates a new branch, which can easily be fetched to the other repository.

Now I used git subtree add to paste the directory back into the second repository.

If I look at gitk or git log --decorate --graph everything looks fine. All commits are present as expected. Also all the files are present as expected.

But when I try to see the history of a transplanted file using git log -- transplanted_dir/somefile, I only see the one "merge" commit, resulting from the git subtree add.

Why do I see the commits in gitk above, but not in the log of a single file?

If I do a simple git merge, I can see the history of each file, but the files will, of course not live in a subfolder.

What is the right way to integrate the moved commits into the other repository?

Detailed example commands to reproduce situation:

#create two repositories:
git init a
git init b

# create directory dir with some history
cd a
mkdir dir
echo 1 > dir/file
git add .
git commit -am 1
echo 2 > dir/file
git commit -am 2
echo 3 > dir/file
echo 3 > otherfile
git add .
git commit -am 3

#split subtree
git subtree split --prefix dir -b split

#create a commit on repo b
cd ../b
mkdir otherdir
touch otherdir/file
git add .
git commit -am init

#fetch split branch of repo a
git fetch ../a split
git co -b split FETCH_HEAD
git log --decorate --graph --name-status 
git co master

# add commits to repo b
git subtree add --prefix somedir split

# this looks fine:
git log --decorate --graph --name-status

# no history here - Why?
git log --decorate --graph --name-status somedir/file
git log --decorate --graph --name-status --follow somedir/file
like image 271
michas Avatar asked Oct 21 '22 10:10

michas


1 Answers

Alright, reading the source cleared things up.

git subtree add is pretty ugly: It first uses git read-tree to add the current version without any history into the given directory. Afterwards it uses git commit-tree to create a fake merge commit to attach the old history containing the unprefixed files.

On the other hand, now the prefixed file at HEAD and the unprefixed one in HEAD^2 should be exactly the same and should be recognized as a move by --follow.

Unfortuately it is not recognized as such. No idea why.

The best solution is probably to add an explicit commit moving the files to the new directory and do a normal merge. - An alternative is to rewrite the history of the transplanted directory as described in How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?.

For my situation git subtree add is bad, a normal git merge with a correctly prepared subtree seems to be exactly the right thing.

like image 188
michas Avatar answered Oct 27 '22 20:10

michas