Re: [PATCH 1/4] subtree: support split --rejoin --squash
Hi again, After using the patched git-subtree (with patches 1 to 3) for a while, I suspect the added functionality does not do exactly what I wanted. So yes, now when doing a rejoin, the squash of the split commits is used. But how can I push this squash instead of the individual commits? The problem is I don't know how to reference that squashed commit. I tried adding the --branch option but it adds the branch to the top of the individual commits so no luck there. This is maybe obvious but I'm not at ease with commit references in git. Pierre 2014/1/23 Matthew Ogilvie mmogilvi_...@miniinfo.net: On Wed, Jan 22, 2014 at 03:58:28PM +0100, Pierre Penninckx wrote: 2013/12/7 Matthew Ogilvie mmogilvi_...@miniinfo.net Subject: [PATCH 1/4] subtree: support split --rejoin --squash Allow using --squash with git subtree split --rejoin. It will still split off (and save to --branch) the complete subtree history, but the merge done for the --rejoin will be merging a squashed representation of the new subtree commits, instead of the commits themselves (similar to how git subtree merge --squash works). Signed-off-by: Matthew Ogilvie mmogilvi_...@miniinfo.net --- I can think of a couple of possible objections to this patch. Are these (or any others) worth fixing? 1. Perhaps someone want the saved subtree (--branch) to have a squashed representation as well, as an option? Maybe we need two different --squash options? Something like --rejoin-squash? 2. It could definitely use some automated tests. In fact, pre-existing --squash functionality is hardly tested at all, either. See patch 4 comments for a script I use to help with mostly-manual testing. Sorry to bother you with this again, but I was wondering if those patches would be integrated into git anytime soon. And if not, if there is something I can do to help. I found them by the way, thanks a lot! Pierre I'm not sure when or if the patches will make it in. Junio's weekly What's cooking... email has asked for Comments? about them for the past several weeks, but I have yet to see anyone actually comment about them. Searching throught the last couple of years of mailing list archives for subtree reveals a general lack of a active maintainer(s) to help review and improve patches for git subtree. Given the general lack of help and feedback, it is understandable that Junio has largely limited inclusion of subtree patches to trivially obvious bug fixes. - Matthew Ogilvie -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] subtree: add squash handling for split and push
Hi Matthew, Clarification: The current documentation (correctly) doesn't actually claim to support split --squash, but it does erroneously claim to support push --squash ». Yes indeed. ;) It looks like your patch is basically squashing the new subtree commits together, throwing out those commits completely, and only keeping the squashed commit in the split —branch. Exactly. 3. (new/better) Use split --rejoin --squash (or some other invocation to be defined). The subtree branch is generated exactly like normal, including fine-grained history. But instead of merging the subtree branch directly, --rejoin will squash all the changes to that branch, and merge in just the squash (referencing the unsquashed split branch tip in the commit message, but not the parent). Subsequent splits can run very fast, while the --rejoin only generated two commits instead of the potentially thousands of (mostly) duplicates it would pull in without the --squash ». Isn’t this similar to my way? I mean I too generate the fine-grained history and make a squash afterwards, no? I also don’t get why would your solution generate any duplicates. Would mine generate some? I suppose the two answers are linked. I have this third option half-coded already, but I still need to finish it. I’m eager to test it! Does anyone have any suggestions about the UI? Do we need to also support Pierre Penninckx's split --squash semantics somehow? If so, what command line options would allow for distinguishing the two cases? Maybe `split --rejoin-squash` since it’s really a third way? I intended to use `push --squash` to send a squash of the commits to hide the actual tinkering. So if your way allows to do it, I vote to stick with yours. Regards, Pierre Penninckx-- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] subtree: add squash handling for split and push
From 2763be1fe68d07af60945762178b8494228eb45f Mon Sep 17 00:00:00 2001 From: Pierre Penninckx ibizapea...@gmail.com Date: Sat, 23 Nov 2013 20:03:20 +0100 Subject: [PATCH] subtree: add squash handling for split and push The documentation of subtree says that the --squash option can be used for add, merge, split and push subtree commands but only add and merge is implemented. cmd_push() simply forwards the --squash argument to subtree split. All the job is done by cmd_split(). cmd_split() first lets split do it's job: finding which commits need to be extracted. Now we remember which commit is the parent of the first extracted commit. When this step is done, cmd_split() generates a squash of the new commits, starting from the aforementioned parent to the last extracted commit. This new commit's sha1 is then used for the rest of the script. Tests verify that `git subtree split/push --squash` makes only one commit where `git subtree split/push` without squash makes two. --- contrib/subtree/git-subtree.sh | 20 ++- contrib/subtree/t/t7900-subtree.sh | 40 ++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 7d7af03..76eb136 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -183,6 +183,7 @@ cache_set() newrev=$2 if [ $oldrev != latest_old \ -a $oldrev != latest_new \ +-a $oldrev != firstnewparents \ -a -e $cachedir/$oldrev ]; then die cache for $oldrev already exists! fi @@ -603,6 +604,10 @@ cmd_split() debug parents: $parents newparents=$(cache_get $parents) debug newparents: $newparents + if [ -z $(cache_get firstnewparents) ]; then + cache_set firstnewparents $newparents + debug firstnewparents: $(cache_get firstnewparents) + fi tree=$(subtree_for_commit $rev $dir) debug tree is: $tree @@ -625,11 +630,18 @@ cmd_split() cache_set latest_new $newrev cache_set latest_old $rev done || exit $? + latest_new=$(cache_get latest_new) if [ -z $latest_new ]; then die No new revisions were found fi + if [ -n $squash ]; then + from=$(cache_get firstnewparents) + latest_new=$(new_squash_commit $from $from $latest_new) || exit $? + debug New squash commit: $latest_new + fi + if [ -n $rejoin ]; then debug Merging split branch into HEAD... latest_old=$(cache_get latest_old) @@ -711,11 +723,17 @@ cmd_push() if [ $# -ne 2 ]; then die You must provide repository refspec fi + + squash_cmd= + if [ -n $squash ]; then + squash_cmd=--squash + fi + if [ -e $dir ]; then repository=$1 refspec=$2 echo git push using: $repository $refspec - localrev=$(git subtree split --prefix=$prefix) || die + localrev=$(git subtree split --prefix=$prefix $squash_cmd) || die git push $repository $localrev:refs/heads/$refspec else die '$dir' must already exist. Try 'git subtree add'. diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 66ce4b0..04eea94 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -31,6 +31,16 @@ check_equal() fi } +check_not_equal() +{ +check_equal $1 $2 +if [ $? -eq 0 ]; then +return 1 +else +return 0 +fi +} + fixnl() { t= @@ -161,6 +171,36 @@ test_expect_success 'fetch new subproj history' ' git branch sub2 FETCH_HEAD ' +test_expect_success 'check that split and split --squash produce different commits' ' +split=$(git subtree split --prefix=subdir) +split_squash=$(git subtree split --prefix=subdir --squash) +check_not_equal $split $split_squash +' + +test_expect_success 'check that split and split --squash produce same diff' ' +split=$(git subtree split --prefix=subdir) +split_squash=$(git subtree split --prefix=subdir --squash) +split_diff=$(git diff sub1 $split) +split_squash_diff=$(git diff sub1 $split_squash) +check_equal $split_diff $split_squash_diff +' + +test_expect_success 'check that push introduces two commits in subproj' ' +git subtree push --prefix=subdir subproj mainline +cd subproj +check_equal $(git rev-parse mainline~2) $(git rev-parse sub1) +git branch -D mainline +cd .. +' + +test_expect_success 'check that push --squash introduces only one commit in subproj' ' +git subtree push