From: Matthew Ogilvie <mmogilvi_git@miniinfo.net>
To: git@vger.kernel.org
Cc: greened@obbligato.org, amdmi3@amdmi3.ru, john@keeping.me.uk,
techlivezheng@gmail.com, apenwarr@gmail.com,
Matthew Ogilvie <mmogilvi_git@miniinfo.net>
Subject: [PATCH 1/4] subtree: support split --rejoin --squash
Date: Sat, 7 Dec 2013 11:21:22 -0700 [thread overview]
Message-ID: <1386440485-3092-1-git-send-email-mmogilvi_git@miniinfo.net> (raw)
In-Reply-To: <1B2468D5-F0B7-4D11-8710-A3A7C8D66215@gmail.com>
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_git@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.
contrib/subtree/git-subtree.sh | 60 +++++++++++++++++++++++++++++++----------
contrib/subtree/git-subtree.txt | 27 ++++++++++++-------
2 files changed, 63 insertions(+), 24 deletions(-)
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 7d7af03..998a9c5 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -20,14 +20,13 @@ q quiet
d show debug messages
P,prefix= the name of the subdir to split out
m,message= use the given message as the commit message for the merge commit
+squash merge subtree changes as a single commit
options for 'split'
annotate= add a prefix to commit message of new commits
b,branch= create a new branch from the split subtree
ignore-joins ignore prior --rejoin commits
onto= try connecting new tree to an existing one
rejoin merge the new branch back into HEAD
- options for 'add', 'merge', 'pull' and 'push'
-squash merge subtree changes as a single commit
"
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
@@ -229,13 +228,19 @@ find_latest_squash()
sq=
main=
sub=
+ par1=
+ par2=
git log --grep="^git-subtree-dir: $dir/*\$" \
- --pretty=format:'START %H%n%s%n%n%b%nEND%n' HEAD |
- while read a b junk; do
- debug "$a $b $junk"
+ --pretty=format:'START %H %P%n%s%n%n%b%nEND%n' HEAD |
+ while read a b c d junk; do
+ debug "$a $b $c $d $junk"
debug "{{$sq/$main/$sub}}"
case "$a" in
- START) sq="$b" ;;
+ START)
+ sq="$b"
+ par1="$c"
+ par2="$d"
+ ;;
git-subtree-mainline:) main="$b" ;;
git-subtree-split:) sub="$b" ;;
END)
@@ -243,7 +248,8 @@ find_latest_squash()
if [ -n "$main" ]; then
# a rejoin commit?
# Pretend its sub was a squash.
- sq="$sub"
+ assert [ "$main" = "$par1" ]
+ sq="$par2"
fi
debug "Squash found: $sq $sub"
echo "$sq" "$sub"
@@ -252,6 +258,8 @@ find_latest_squash()
sq=
main=
sub=
+ par1=
+ par2=
;;
esac
done
@@ -565,6 +573,13 @@ cmd_split()
debug "Splitting $dir..."
cache_setup || exit $?
+ if [ -n "$rejoin" ]; then
+ ensure_clean
+ if [ -n "$squash" ]; then
+ first_split="$(find_latest_squash "$dir")"
+ fi
+ fi
+
if [ -n "$onto" ]; then
debug "Reading history for --onto=$onto..."
git rev-list $onto |
@@ -630,13 +645,6 @@ cmd_split()
die "No new revisions were found"
fi
- if [ -n "$rejoin" ]; then
- debug "Merging split branch into HEAD..."
- latest_old=$(cache_get latest_old)
- git merge -s ours \
- -m "$(rejoin_msg $dir $latest_old $latest_new)" \
- $latest_new >&2 || exit $?
- fi
if [ -n "$branch" ]; then
if rev_exists "refs/heads/$branch"; then
if ! rev_is_descendant_of_branch $latest_new $branch; then
@@ -649,6 +657,30 @@ cmd_split()
git update-ref -m 'subtree split' "refs/heads/$branch" $latest_new || exit $?
say "$action branch '$branch'"
fi
+ if [ -n "$rejoin" ]; then
+ debug "Merging split branch into HEAD..."
+ latest_old=$(cache_get latest_old)
+ new=$latest_new
+
+ if [ -n "$squash" ]; then
+ debug "Squashing split branch."
+
+ set $first_split
+ old=$1
+ sub=$2
+ if [ "$sub" = "$latest_new" ]; then
+ say "Subtree is already at commit $latest_new."
+ exit 0
+ fi
+ new=$(new_squash_commit "$old" "$sub" "$latest_new") \
+ || exit $?
+ debug "New squash commit: $new"
+ fi
+
+ git merge -s ours -m \
+ "$(rejoin_msg $dir $latest_old $latest_new)" \
+ $new >&2 || exit $?
+ fi
echo $latest_new
exit 0
}
diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
index e0957ee..92e7a4d 100644
--- a/contrib/subtree/git-subtree.txt
+++ b/contrib/subtree/git-subtree.txt
@@ -140,18 +140,20 @@ OPTIONS
want to manipulate. This option is mandatory
for all commands.
+
+OPTIONS FOR add, merge, pull, rejoin
+----------------------------------
-m <message>::
--message=<message>::
- This option is only valid for add, merge and pull (unsure).
- Specify <message> as the commit message for the merge commit.
+ This option is only valid for add, merge, pull, and
+ split '--rejoin'.
+ Specify <message> as the commit message for the merge commit.
-OPTIONS FOR add, merge, push, pull
-----------------------------------
--squash::
- This option is only valid for add, merge, push and pull
- commands.
-
+ This option is only valid for add, merge, pull, and
+ split '--rejoin'.
+
Instead of merging the entire history from the subtree
project, produce only a single commit that contains all
the differences you want to merge, and then merge that
@@ -180,6 +182,10 @@ OPTIONS FOR add, merge, push, pull
local repository remain intact and can be later split
and send upstream to the subproject.
+ Using '--squash' with split '--rejoin' only squashes
+ the merge back to the mainline, not the synthetic subtree
+ history.
+
OPTIONS FOR split
-----------------
@@ -251,9 +257,10 @@ OPTIONS FOR split
showing an extra copy of every new commit that was
created (the original, and the synthetic one).
- If you do all your merges with '--squash', don't use
- '--rejoin' when you split, because you don't want the
- subproject's history to be part of your project anyway.
+ Fortunately, you can use '--squash' with '--rejoin'
+ to simplify a sequence of synthetic commits as a
+ single squashed commit in the mainline. The subtree
+ will still have full history.
EXAMPLE 1. Add command
--
1.8.3.2
next prev parent reply other threads:[~2013-12-07 18:24 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-23 20:18 [PATCH] subtree: add squash handling for split and push Pierre Penninckx
2013-11-28 18:23 ` Matthew Ogilvie
2013-11-28 22:58 ` Pierre Penninckx
2013-12-07 18:21 ` Matthew Ogilvie [this message]
2013-12-07 18:21 ` [PATCH 2/4] subtree: allow --squash and --message with push Matthew Ogilvie
2013-12-07 18:21 ` [PATCH 3/4] subtree: add --edit option Matthew Ogilvie
2013-12-07 18:21 ` [PATCH/BAD 4/4] subtree: poor bugfix for split new commits with parents before previous split Matthew Ogilvie
2013-12-10 22:46 ` [PATCH 1/4] subtree: support split --rejoin --squash Junio C Hamano
[not found] <20131207185853.GA3353@comcast.net>
[not found] ` <CAMzgWy18wH4_Ds00x7UASQjLgN8LiEucFSZFp-5PJio_pEwmnA@mail.gmail.com>
2014-01-23 3:59 ` Matthew Ogilvie
2014-01-23 8:51 ` Pierre Penninckx
2014-01-23 14:42 ` Matthew Ogilvie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1386440485-3092-1-git-send-email-mmogilvi_git@miniinfo.net \
--to=mmogilvi_git@miniinfo.net \
--cc=amdmi3@amdmi3.ru \
--cc=apenwarr@gmail.com \
--cc=git@vger.kernel.org \
--cc=greened@obbligato.org \
--cc=john@keeping.me.uk \
--cc=techlivezheng@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).