I am using git subtree
to organize my git repositories. Let's say I have a main repository called repo
and a library called lib
.
I successfully "imported" the lib
repository by squashing its history. I would now like to contribute back to lib
by squashing the history too. This does not seem to work: I specify the --squash
option to git subtree push
but when looking at the history I still send all the commits.
Here is a script showing the minimal commands needed to reproduce the problem:
#!/bin/bash
rm -rf lib lib-work repo
# repo is the main repository
git init repo
# lib is the 'subtreed' repository (bare to accept pushes)
git init --bare lib
git clone lib lib-work
cd lib-work
# adding a bunch of commits to lib
echo "v1" > README
git add README
git commit -m 'lib commit 1'
echo "v2" > README
git add README
git commit -m 'lib commit 2'
echo "v3" > README
git add README
git commit -m 'lib commit 3'
git push origin master
cd ..
cd repo
# adding initial commit to have a valid HEAD
echo "v1" > README
git add README
git commit -m 'repo commit 1'
git remote add lib ../lib
git subtree add --prefix lib lib master --squash
echo "v4" > lib/README
git add lib/README
git commit -m 'repo commit 2'
echo "v5" > lib/README
git add lib/README
git commit -m 'repo commit 3'
echo "v6" > lib/README
git add lib/README
git commit -m 'repo commit 4'
#git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit
# "not working" command :
git subtree push --prefix lib lib master --squash
# pretty print the history
git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit
cd ../lib
echo
git log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s%Creset' --abbrev-commit
git log
showing the problemThe output of the two git log blabla
commands are:
* b075d5e - (HEAD, master) repo commit 4
* ebdc7c7 - repo commit 3
* 9f1edab - repo commit 2
* 3d48bca - Merge commit '34e16a547819da7e228f3add35efe86197d2ddcb' as 'lib'
|\
| * 34e16a5 - Squashed 'lib/' content from commit 2643625
* 3f1490c - repo commit 1
* 1f86fe3 - (lib/master) repo commit 4
* 9f1639a - repo commit 3
* 8bd01bd - repo commit 2
* 2643625 - lib commit 3
* 3d64b8c - lib commit 2
* aba9fcb - lib commit 1
and :
* 1f86fe3 - (HEAD, master) repo commit 4
* 9f1639a - repo commit 3
* 8bd01bd - repo commit 2
* 2643625 - lib commit 3
* 3d64b8c - lib commit 2
* aba9fcb - lib commit 1
As you can see, lib sees the "repo commit 2,3,4"
although I specified the squash option.
The other way around worked hence the Squashed 'lib/' content from commit f28bf8e
.
I tried on windows with git version 1.8.1.msysgit.1 and on linux with git version 1.8.3.4.
So why doesn't the --squash
option do a squash?
Why does lib/master appears in the log of the repo
repository ?
Knowing it appears only after the "failed" git push
: if you uncomment the first git log blabla
you get the following output showing the stashed history but no sign of lib/master :
* b075d5e - (HEAD, master) repo commit 4
* ebdc7c7 - repo commit 3
* 9f1edab - repo commit 2
* 3d48bca - Merge commit '34e16a547819da7e228f3add35efe86197d2ddcb' as 'lib'
|\
| * 34e16a5 - Squashed 'lib/' content from commit 2643625
* 3f1490c - repo commit 1
It is possible that this is an error in the documentation of the subtree command.
The manual in git states:
options for 'add', 'merge', 'pull' and 'push'
--squash merge subtree changes as a single commit
If you check the more extended documentation in the original subtree project you will notice that the --squash
option is only explained for add
and merge
, as the functionality is described for the process of bringing content into your repository. Since pull
is a modified form of merge, it is also implied that it can use --squash
.
The push
in the manual list what does not make sense. The git subtree push
subcommand is a combination of git subtree split
and git push
. This means that --squash
should be an option also supported by split
, but split
is not listed in the manual list. It is neither ever stated in the documentation that it can use --squash
.
The --squash
option is indeed accepted by split
and push
without error, but after experiment with it it seems it makes no difference, just as your example states. My take is that it is there by mistake and just ignored by the split
and push
commands.