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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With