mirror of
https://github.com/git/git
synced 2024-08-28 03:59:25 +00:00
subtree: allow --squash to be used with --rejoin
Besides being a genuinely useful thing to do, this also just makes sense and harmonizes which flags may be used when. `git subtree split --rejoin` amounts to "automatically go ahead and do a `git subtree merge` after doing the main `git subtree split`", so it's weird and arbitrary that you can't pass `--squash` to `git subtree split --rejoin` like you can `git subtree merge`. It's weird that `git subtree split --rejoin` inherits `git subtree merge`'s `--message` but not `--squash`. Reconcile the situation by just having `split --rejoin` actually just call `merge` internally (or call `add` instead, as appropriate), so it can get access to the full `merge` behavior, including `--squash`. Signed-off-by: Luke Shumaker <lukeshu@datawire.io> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
6468784dd2
commit
cb6551447b
|
@ -33,15 +33,15 @@ h,help show the help
|
||||||
q quiet
|
q quiet
|
||||||
d show debug messages
|
d show debug messages
|
||||||
P,prefix= the name of the subdir to split out
|
P,prefix= the name of the subdir to split out
|
||||||
m,message= use the given message as the commit message for the merge commit
|
|
||||||
options for 'split'
|
options for 'split'
|
||||||
annotate= add a prefix to commit message of new commits
|
annotate= add a prefix to commit message of new commits
|
||||||
b,branch= create a new branch from the split subtree
|
b,branch= create a new branch from the split subtree
|
||||||
ignore-joins ignore prior --rejoin commits
|
ignore-joins ignore prior --rejoin commits
|
||||||
onto= try connecting new tree to an existing one
|
onto= try connecting new tree to an existing one
|
||||||
rejoin merge the new branch back into HEAD
|
rejoin merge the new branch back into HEAD
|
||||||
options for 'add' and 'merge' (also: 'pull')
|
options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')
|
||||||
squash merge subtree changes as a single commit
|
squash merge subtree changes as a single commit
|
||||||
|
m,message= use the given message as the commit message for the merge commit
|
||||||
"
|
"
|
||||||
|
|
||||||
arg_debug=
|
arg_debug=
|
||||||
|
@ -346,7 +346,8 @@ find_latest_squash () {
|
||||||
then
|
then
|
||||||
# a rejoin commit?
|
# a rejoin commit?
|
||||||
# Pretend its sub was a squash.
|
# Pretend its sub was a squash.
|
||||||
sq="$sub"
|
sq=$(git rev-parse --verify "$sq^2") ||
|
||||||
|
die
|
||||||
fi
|
fi
|
||||||
debug "Squash found: $sq $sub"
|
debug "Squash found: $sq $sub"
|
||||||
echo "$sq" "$sub"
|
echo "$sq" "$sub"
|
||||||
|
@ -453,6 +454,13 @@ add_msg () {
|
||||||
else
|
else
|
||||||
commit_message="Add '$dir/' from commit '$latest_new'"
|
commit_message="Add '$dir/' from commit '$latest_new'"
|
||||||
fi
|
fi
|
||||||
|
if test -n "$arg_split_rejoin"
|
||||||
|
then
|
||||||
|
# If this is from a --rejoin, then rejoin_msg has
|
||||||
|
# already inserted the `git-subtree-xxx:` tags
|
||||||
|
echo "$commit_message"
|
||||||
|
return
|
||||||
|
fi
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
$commit_message
|
$commit_message
|
||||||
|
|
||||||
|
@ -775,7 +783,12 @@ cmd_add_commit () {
|
||||||
rev=$(git rev-parse --verify "$1^{commit}") || exit $?
|
rev=$(git rev-parse --verify "$1^{commit}") || exit $?
|
||||||
|
|
||||||
debug "Adding $dir as '$rev'..."
|
debug "Adding $dir as '$rev'..."
|
||||||
git read-tree --prefix="$dir" $rev || exit $?
|
if test -z "$arg_split_rejoin"
|
||||||
|
then
|
||||||
|
# Only bother doing this if this is a genuine 'add',
|
||||||
|
# not a synthetic 'add' from '--rejoin'.
|
||||||
|
git read-tree --prefix="$dir" $rev || exit $?
|
||||||
|
fi
|
||||||
git checkout -- "$dir" || exit $?
|
git checkout -- "$dir" || exit $?
|
||||||
tree=$(git write-tree) || exit $?
|
tree=$(git write-tree) || exit $?
|
||||||
|
|
||||||
|
@ -815,6 +828,11 @@ cmd_split () {
|
||||||
die "You must provide exactly one revision. Got: '$*'"
|
die "You must provide exactly one revision. Got: '$*'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test -n "$arg_split_rejoin"
|
||||||
|
then
|
||||||
|
ensure_clean
|
||||||
|
fi
|
||||||
|
|
||||||
debug "Splitting $dir..."
|
debug "Splitting $dir..."
|
||||||
cache_setup || exit $?
|
cache_setup || exit $?
|
||||||
|
|
||||||
|
@ -857,10 +875,13 @@ cmd_split () {
|
||||||
then
|
then
|
||||||
debug "Merging split branch into HEAD..."
|
debug "Merging split branch into HEAD..."
|
||||||
latest_old=$(cache_get latest_old) || exit $?
|
latest_old=$(cache_get latest_old) || exit $?
|
||||||
git merge -s ours \
|
arg_addmerge_message="$(rejoin_msg "$dir" "$latest_old" "$latest_new")" || exit $?
|
||||||
--allow-unrelated-histories \
|
if test -z "$(find_latest_squash "$dir")"
|
||||||
-m "$(rejoin_msg "$dir" "$latest_old" "$latest_new")" \
|
then
|
||||||
"$latest_new" >&2 || exit $?
|
cmd_add "$latest_new" >&2 || exit $?
|
||||||
|
else
|
||||||
|
cmd_merge "$latest_new" >&2 || exit $?
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if test -n "$arg_split_branch"
|
if test -n "$arg_split_branch"
|
||||||
then
|
then
|
||||||
|
|
|
@ -109,9 +109,6 @@ settings passed to 'split' (such as '--annotate') are the same.
|
||||||
Because of this, if you add new commits and then re-split, the new
|
Because of this, if you add new commits and then re-split, the new
|
||||||
commits will be attached as commits on top of the history you
|
commits will be attached as commits on top of the history you
|
||||||
generated last time, so 'git merge' and friends will work as expected.
|
generated last time, so 'git merge' and friends will work as expected.
|
||||||
+
|
|
||||||
Note that if you use '--squash' when you merge, you should usually not
|
|
||||||
just '--rejoin' when you split.
|
|
||||||
|
|
||||||
pull <repository> <remote-ref>::
|
pull <repository> <remote-ref>::
|
||||||
Exactly like 'merge', but parallels 'git pull' in that
|
Exactly like 'merge', but parallels 'git pull' in that
|
||||||
|
@ -124,8 +121,8 @@ push <repository> <remote-ref>::
|
||||||
<remote-ref>. This can be used to push your subtree to
|
<remote-ref>. This can be used to push your subtree to
|
||||||
different branches of the remote repository.
|
different branches of the remote repository.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS FOR ALL COMMANDS
|
||||||
-------
|
------------------------
|
||||||
-q::
|
-q::
|
||||||
--quiet::
|
--quiet::
|
||||||
Suppress unnecessary output messages on stderr.
|
Suppress unnecessary output messages on stderr.
|
||||||
|
@ -140,15 +137,11 @@ OPTIONS
|
||||||
want to manipulate. This option is mandatory
|
want to manipulate. This option is mandatory
|
||||||
for all commands.
|
for all commands.
|
||||||
|
|
||||||
-m <message>::
|
OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')
|
||||||
--message=<message>::
|
-----------------------------------------------------------------
|
||||||
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' AND 'merge' (ALSO: 'pull')
|
|
||||||
--------------------------------------------
|
|
||||||
These options for 'add' and 'merge' may also be given to 'pull' (which
|
These options for 'add' and 'merge' may also be given to 'pull' (which
|
||||||
wraps 'merge').
|
wraps 'merge') and 'split --rejoin' (which wraps either 'add' or
|
||||||
|
'merge' as appropriate).
|
||||||
|
|
||||||
--squash::
|
--squash::
|
||||||
Instead of merging the entire history from the subtree project, produce
|
Instead of merging the entire history from the subtree project, produce
|
||||||
|
@ -176,6 +169,9 @@ Whether or not you use '--squash', changes made in your local repository
|
||||||
remain intact and can be later split and send upstream to the
|
remain intact and can be later split and send upstream to the
|
||||||
subproject.
|
subproject.
|
||||||
|
|
||||||
|
-m <message>::
|
||||||
|
--message=<message>::
|
||||||
|
Specify <message> as the commit message for the merge commit.
|
||||||
|
|
||||||
OPTIONS FOR 'split'
|
OPTIONS FOR 'split'
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -229,9 +225,8 @@ Unfortunately, using this option results in 'git log' showing an extra
|
||||||
copy of every new commit that was created (the original, and the
|
copy of every new commit that was created (the original, and the
|
||||||
synthetic one).
|
synthetic one).
|
||||||
+
|
+
|
||||||
If you do all your merges with '--squash', don't use '--rejoin' when you
|
If you do all your merges with '--squash', make sure you also use
|
||||||
split, because you don't want the subproject's history to be part of
|
'--squash' when you 'split --rejoin'.
|
||||||
your project anyway.
|
|
||||||
|
|
||||||
|
|
||||||
EXAMPLE 1. 'add' command
|
EXAMPLE 1. 'add' command
|
||||||
|
|
|
@ -324,6 +324,62 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'split "sub dir"/ with --rejoin and --squash' '
|
||||||
|
subtree_test_create_repo "$test_count" &&
|
||||||
|
subtree_test_create_repo "$test_count/sub proj" &&
|
||||||
|
test_create_commit "$test_count" main1 &&
|
||||||
|
test_create_commit "$test_count/sub proj" sub1 &&
|
||||||
|
(
|
||||||
|
cd "$test_count" &&
|
||||||
|
git fetch ./"sub proj" HEAD &&
|
||||||
|
git subtree add --prefix="sub dir" --squash FETCH_HEAD
|
||||||
|
) &&
|
||||||
|
test_create_commit "$test_count" "sub dir"/main-sub1 &&
|
||||||
|
test_create_commit "$test_count" main2 &&
|
||||||
|
test_create_commit "$test_count/sub proj" sub2 &&
|
||||||
|
test_create_commit "$test_count" "sub dir"/main-sub2 &&
|
||||||
|
(
|
||||||
|
cd "$test_count" &&
|
||||||
|
git subtree pull --prefix="sub dir" --squash ./"sub proj" HEAD &&
|
||||||
|
MAIN=$(git rev-parse --verify HEAD) &&
|
||||||
|
SUB=$(git -C "sub proj" rev-parse --verify HEAD) &&
|
||||||
|
|
||||||
|
SPLIT=$(git subtree split --prefix="sub dir" --annotate="*" --rejoin --squash) &&
|
||||||
|
|
||||||
|
test_must_fail git merge-base --is-ancestor $SUB HEAD &&
|
||||||
|
test_must_fail git merge-base --is-ancestor $SPLIT HEAD &&
|
||||||
|
git rev-list HEAD ^$MAIN >commit-list &&
|
||||||
|
test_line_count = 2 commit-list &&
|
||||||
|
test "$(git rev-parse --verify HEAD:)" = "$(git rev-parse --verify $MAIN:)" &&
|
||||||
|
test "$(git rev-parse --verify HEAD:"sub dir")" = "$(git rev-parse --verify $SPLIT:)" &&
|
||||||
|
test "$(git rev-parse --verify HEAD^1)" = $MAIN &&
|
||||||
|
test "$(git rev-parse --verify HEAD^2)" != $SPLIT &&
|
||||||
|
test "$(git rev-parse --verify HEAD^2:)" = "$(git rev-parse --verify $SPLIT:)" &&
|
||||||
|
test "$(last_commit_subject)" = "Split '\''sub dir/'\'' into commit '\''$SPLIT'\''"
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'split then pull "sub dir"/ with --rejoin and --squash' '
|
||||||
|
# 1. "add"
|
||||||
|
subtree_test_create_repo "$test_count" &&
|
||||||
|
subtree_test_create_repo "$test_count/sub proj" &&
|
||||||
|
test_create_commit "$test_count" main1 &&
|
||||||
|
test_create_commit "$test_count/sub proj" sub1 &&
|
||||||
|
git -C "$test_count" subtree --prefix="sub dir" add --squash ./"sub proj" HEAD &&
|
||||||
|
|
||||||
|
# 2. commit from parent
|
||||||
|
test_create_commit "$test_count" "sub dir"/main-sub1 &&
|
||||||
|
|
||||||
|
# 3. "split --rejoin --squash"
|
||||||
|
git -C "$test_count" subtree --prefix="sub dir" split --rejoin --squash &&
|
||||||
|
|
||||||
|
# 4. "pull --squash"
|
||||||
|
test_create_commit "$test_count/sub proj" sub2 &&
|
||||||
|
git -C "$test_count" subtree -d --prefix="sub dir" pull --squash ./"sub proj" HEAD &&
|
||||||
|
|
||||||
|
test_must_fail git merge-base HEAD FETCH_HEAD
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'split "sub dir"/ with --branch' '
|
test_expect_success 'split "sub dir"/ with --branch' '
|
||||||
subtree_test_create_repo "$test_count" &&
|
subtree_test_create_repo "$test_count" &&
|
||||||
subtree_test_create_repo "$test_count/sub proj" &&
|
subtree_test_create_repo "$test_count/sub proj" &&
|
||||||
|
|
Loading…
Reference in a new issue