From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
While preparing to make some minor "git merge" changes, I noticed that
the old merge script does not pass all tests any more. Since it can
be easier to prototype in shell and then port to C, I think that is
worth fixing.
Of course this is not urgent at all.
Patch 1 fixes a minor bug that the scripted implementation does not
suffer from, illustrated by the test "merge early part of c2" from
t7600-merge.sh.
The underlying problem is a subtlety in the resolve_ref() API (from
v0.99.8~13, Use resolve_ref() to implement read_ref(), 2005-09-30):
the "reading" argument to resolve_ref() should usually be true, but
that is not obvious to newcomers.
Patches 2-7 are minor test changes. They are early in the series
to give flexibility about when to merge them.
Patches 8-10 expose functionality used by merge when handling octopus
merges. merge-base --octopus is get_octopus_merge_bases(), used to
provide basis arguments when running the "git merge-octopus" command.
Of course the latter does not care about its basis arguments, but
that is a topic for another series. merge-base --independent is
reduce_refs(), used to reduce the parent list when --no-ff is not
in use.
These are analagous to show-branch --merge-base and
show-branch --independent but are slower and can be used with more
than 25 refs.
Patch 11 exposes the functionality from fmt-merge-msg needed to
implement merge --log -m.
Patches 12 and later are ports of various patches to builtin/merge.c.
I did the bare minimum to make tests pass. :)
Patches are against jn/merge-renormalize~2 (rerere: migrate to
parse-options API) from pu, because without that,
"rerere --rerere-autoupdate" does not work.
Thoughts?
Jonathan Nieder (24):
merge: do not mistake (ancestor of) tag for branch
t7600 (merge): modernize style
t7600 (merge): do not launch gitk for --debug
t7600 (merge): check reflog entry
t7600 (merge): test merge from branch yet to be born
t6010 (merge-base): modernize style
t6200 (fmt-merge-msg): style nitpicks
Documentation: add a SEE ALSO section for merge-base
merge-base --octopus to mimic show-branch --merge-base
merge-base --independent to print reduced parent list in a merge
fmt-merge-msg -m to replace subject line
merge script: --squash, --ff from unborn branch are errors
merge script: tweak unmerged files message to match builtin
merge script: refuse to merge during merge
merge script: improve log message subject
merge script: merge -X<option>
merge script: allow custom strategies
merge script: forbid merge -s index
merge script: handle -m --log correctly
merge script: handle many-way octopus
merge script: --ff-only to disallow true merge
merge script: handle --no-ff --no-commit correctly
merge script: notice @{-1} shorthand
merge script: learn --[no-]rerere-autoupdate
Documentation/git-fmt-merge-msg.txt | 9 +-
Documentation/git-merge-base.txt | 34 +++-
builtin/fmt-merge-msg.c | 18 ++-
builtin/merge-base.c | 44 ++++-
builtin/merge.c | 2 +-
contrib/examples/git-merge.sh | 115 ++++++++---
t/t6010-merge-base.sh | 358 +++++++++++++++++++--------------
t/t6200-fmt-merge-msg.sh | 306 ++++++++++++++--------------
t/t7600-merge.sh | 385 +++++++++++++++--------------------
9 files changed, 705 insertions(+), 566 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
If no branch 'foo' exists but a tag 'foo' does, then
git merge foo^ results in
Merge branch 'foo' (early part)
as a commit message, because the relevant code path checks that
refs/heads/foo is a valid refname for writing rather than for
reading.
Signed-off-by: Jonathan Nieder <redacted>
---
builtin/merge.c | 2 +-
t/t7600-merge.sh | 16 ++++++++++++----
2 files changed, 13 insertions(+), 5 deletions(-)
@@ -558,8 +558,11 @@ test_expect_success 'refresh the index before merging' 'gitmergec3'-cat>expected<<EOF-Mergebranch'c5'(earlypart)+cat>expected.branch<<\EOF+Mergebranch'c5-branch'(earlypart)+EOF+cat>expected.tag<<\EOF+Mergecommit'c5~1' EOF test_expect_success'merge early part of c2''
@@ -577,9 +580,14 @@ test_expect_success 'merge early part of c2' 'gitaddc6.c&&gitcommit-mc6&&gittagc6&&+gitbranch-fc5-branchc5&&+gitmergec5-branch~1&&+gitshow-s--pretty=format:%sHEAD>actual.branch&&+gitreset--keepHEAD^&&gitmergec5~1&&-gitshow-s--pretty=format:%sHEAD>actual&&-test_cmpactualexpected+gitshow-s--pretty=format:%sHEAD>actual.tag&&+test_cmpexpected.branchactual.branch&&+test_cmpexpected.tagactual.tag' test_debug'gitk --all'
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Guard setup commands with test_expect_success, so they are easier
to visually skip over and get to the good part. While at it:
- use "printf '%s\n' a b ..." instead of "cat <<EOF" for test
vectors with short lines;
- use test_cmp instead of test foo = bar where possible, for
better output with -v on failure;
- do not go to extraordinary lengths to print a relevant message
when test commands fail. There is a patch in flight that could be
used to restore the nice error messages in a cleaner way.
Cc: Lars Hjemli <redacted>
Cc: Matthieu Moy <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
t/t7600-merge.sh | 282 +++++++++++++++++++-----------------------------------
1 files changed, 98 insertions(+), 184 deletions(-)
@@ -5,189 +5,103 @@test_description='gitmerge-Testingbasicmergeoperations/optionparsing.'+Testingbasicmergeoperations/optionparsing.++![c0]commit0+![c1]commit1+![c2]commit2+![c3]commit3+![c4]c4+![c5]c5+![c6]c6+*[master]Mergecommit'c1'+--------+-[master]Mergecommit'c1'++*[c1]commit1++[c6]c6++[c5]c5+++[c4]c4+++++[c3]commit3++[c2]commit2++++++++*[c0]commit0+' ../test-lib.sh-cat>file<<EOF-1-2-3-4-5-6-7-8-9-EOF+test_expect_success'set up test data and helpers''+printf"%s\n"123456789>file&&+printf"%s\n""1 X"23456789>file.1&&+printf"%s\n"1234"5 X"6789>file.5&&+printf"%s\n"12345678"9 X">file.9&&+printf"%s\n""1 X"23456789>result.1&&+printf"%s\n""1 X"234"5 X"6789>result.1-5&&+printf"%s\n""1 X"234"5 X"678"9 X">result.1-5-9&&-cat>file.1<<EOF-1X-2-3-4-5-6-7-8-9-EOF+create_merge_msgs(){+echo"Merge commit '\''c2'\''">msg.1-5&&+echo"Merge commit '\''c2'\''; commit '\''c3'\''">msg.1-5-9&&+{+echo"Squashed commit of the following:"&&+echo&&+gitlog--no-merges^HEADc1+}>squash.1&&+{+echo"Squashed commit of the following:"&&+echo&&+gitlog--no-merges^HEADc2+}>squash.1-5&&+{+echo"Squashed commit of the following:"&&+echo&&+gitlog--no-merges^HEADc2c3+}>squash.1-5-9&&+echo>msg.nolog&&+{+echo"* commit '\''c3'\'':"&&+echo" commit 3"&&+echo+}>msg.log+}&&-cat>file.5<<EOF-1-2-3-4-5X-6-7-8-9-EOF--cat>file.9<<EOF-1-2-3-4-5-6-7-8-9X-EOF--cat>result.1<<EOF-1X-2-3-4-5-6-7-8-9-EOF--cat>result.1-5<<EOF-1X-2-3-4-5X-6-7-8-9-EOF--cat>result.1-5-9<<EOF-1X-2-3-4-5X-6-7-8-9X-EOF--create_merge_msgs(){-echo"Merge commit 'c2'">msg.1-5&&-echo"Merge commit 'c2'; commit 'c3'">msg.1-5-9&&-echo"Squashed commit of the following:">squash.1&&-echo>>squash.1&&-gitlog--no-merges^HEADc1>>squash.1&&-echo"Squashed commit of the following:">squash.1-5&&-echo>>squash.1-5&&-gitlog--no-merges^HEADc2>>squash.1-5&&-echo"Squashed commit of the following:">squash.1-5-9&&-echo>>squash.1-5-9&&-gitlog--no-merges^HEADc2c3>>squash.1-5-9&&-echo>msg.nolog&&-echo"* commit 'c3':">msg.log&&-echo" commit 3">>msg.log&&-echo>>msg.log-}--verify_diff(){-if!test_cmp"$1""$2"-then-echo"$3"-false-fi-}--verify_merge(){-verify_diff"$2""$1""[OOPS] bad merge result"&&-iftest$(gitls-files-u|wc-l)-gt0-then-echo"[OOPS] unmerged files"-false-fi&&-iftest_must_failgitdiff--exit-code-then-echo"[OOPS] working tree != index"-false-fi&&-iftest-n"$3"-then-gitshow-s--pretty=format:%sHEAD>msg.act&&-verify_diff"$3"msg.act"[OOPS] bad merge message"-fi-}--verify_head(){-iftest"$1"!="$(gitrev-parseHEAD)"-then-echo"[OOPS] HEAD != $1"-false-fi-}--verify_parents(){-i=1-whiletest$#-gt0-do-iftest"$1"!="$(gitrev-parseHEAD^$i)"+verify_merge(){+test_cmp"$2""$1"&&+gitupdate-index--refresh&&+gitdiff--exit-code&&+iftest-n"$3"then-echo"[OOPS] HEAD^$i != $1"-return1+gitshow-s--pretty=format:%sHEAD>msg.act&&+test_cmp"$3"msg.actfi-i=$(expr$i+1)-shift-done-}+}&&-verify_mergeheads(){-i=1-if!test-f.git/MERGE_HEAD-then-echo"[OOPS] MERGE_HEAD is missing"-false-fi&&-whiletest$#-gt0-do-head=$(head-n$i.git/MERGE_HEAD|sed-ne\$p)-iftest"$1"!="$head"-then-echo"[OOPS] MERGE_HEAD $i != $1"+verify_head(){+echo"$1">head.expected&&+gitrev-parseHEAD>head.actual&&+test_cmphead.expectedhead.actual+}&&++verify_parents(){+printf"%s\n""$@">parents.expected&&+>parents.actual&&+i=1&&+whiletest$i-le$#+do+gitrev-parseHEAD^$i>>parents.actual&&+i=$(expr$i+1)||return1-fi-i=$(expr$i+1)-shift-done-}+done&&+test_cmpparents.expectedparents.actual+}&&-verify_no_mergehead(){-iftest-f.git/MERGE_HEAD-then-echo"[OOPS] MERGE_HEAD exists"-false-fi-}+verify_mergeheads(){+printf"%s\n""$@">mergehead.expected&&+test_cmpmergehead.expected.git/MERGE_HEAD+}&&+verify_no_mergehead(){+!test-e.git/MERGE_HEAD+}+' test_expect_success'setup''gitaddfile&&
@@ -316,7 +230,7 @@ test_expect_success 'merge c0 with c1 (squash)' 'verify_mergefileresult.1&&verify_head$c0&&verify_no_mergehead&&-verify_diffsquash.1.git/SQUASH_MSG"[OOPS] bad squash message"+test_cmpsquash.1.git/SQUASH_MSG' test_debug'gitk --all'
@@ -327,7 +241,7 @@ test_expect_success 'merge c0 with c1 (squash, ff-only)' 'verify_mergefileresult.1&&verify_head$c0&&verify_no_mergehead&&-verify_diffsquash.1.git/SQUASH_MSG"[OOPS] bad squash message"+test_cmpsquash.1.git/SQUASH_MSG' test_debug'gitk --all'
@@ -338,7 +252,7 @@ test_expect_success 'merge c1 with c2 (squash)' 'verify_mergefileresult.1-5&&verify_head$c1&&verify_no_mergehead&&-verify_diffsquash.1-5.git/SQUASH_MSG"[OOPS] bad squash message"+test_cmpsquash.1-5.git/SQUASH_MSG' test_debug'gitk --all'
@@ -356,7 +270,7 @@ test_expect_success 'merge c1 with c2 and c3 (squash)' 'verify_mergefileresult.1-5-9&&verify_head$c1&&verify_no_mergehead&&-verify_diffsquash.1-5-9.git/SQUASH_MSG"[OOPS] bad squash message"+test_cmpsquash.1-5-9.git/SQUASH_MSG' test_debug'gitk --all'
@@ -379,7 +293,7 @@ test_expect_success 'merge c1 with c2 (squash in config)' 'verify_mergefileresult.1-5&&verify_head$c1&&verify_no_mergehead&&-verify_diffsquash.1-5.git/SQUASH_MSG"[OOPS] bad squash message"+test_cmpsquash.1-5.git/SQUASH_MSG' test_debug'gitk --all'
@@ -485,17 +399,17 @@ test_expect_success 'merge log message' 'gitreset--hardc0&&gitmerge--no-logc2&&gitshow-s--pretty=format:%bHEAD>msg.act&&-verify_diffmsg.nologmsg.act"[OOPS] bad merge log message"&&+test_cmpmsg.nologmsg.act&&gitmerge--logc3&&gitshow-s--pretty=format:%bHEAD>msg.act&&-verify_diffmsg.logmsg.act"[OOPS] bad merge log message"&&+test_cmpmsg.logmsg.act&&gitreset--hardHEAD^&&gitconfigmerge.logyes&&gitmergec3&&gitshow-s--pretty=format:%bHEAD>msg.act&&-verify_diffmsg.logmsg.act"[OOPS] bad merge log message"+test_cmpmsg.logmsg.act' test_debug'gitk --all'
@@ -567,16 +481,16 @@ EOF test_expect_success'merge early part of c2''gitreset--hardc3&&-echoc4>c4.c&&+echoc4>c4.c&&gitaddc4.c&&gitcommit-mc4&&gittagc4&&-echoc5>c5.c&&+echoc5>c5.c&&gitaddc5.c&&gitcommit-mc5&&gittagc5&&gitreset--hardc3&&-echoc6>c6.c&&+echoc6>c6.c&&gitaddc6.c&&gitcommit-mc6&&gittagc6&&
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Probably as a development aid, this test script runs gitk --all
to allow the driver to inspect history between tests when run
with --debug. As a result, running all tests with --debug
requires closing a long series of gitk displays, one at a time.
Use git log --graph --oneline instead. This way, the history is
available for viewing with "git show" but the test script finishes
without interaction.
Longer term, it would be nice to have an option to run a
user-specified command between tests. This patch does not do
that.
Cc: Lars Hjemli <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
t/t7600-merge.sh | 58 +++++++++++++++++++++++++++---------------------------
1 files changed, 29 insertions(+), 29 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
The details of the reflog message are not important, but
including something sane in the reflog is.
Signed-off-by: Jonathan Nieder <redacted>
---
t/t7600-merge.sh | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Some people like to "git fetch origin && merge origin/master" from
the unborn branch provided when first initializing a repository.
Signed-off-by: Jonathan Nieder <redacted>
---
t/t7600-merge.sh | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Guard setup with test_expect_success, put the opening quote
starting each test on the same line as the test_expect_* invocation,
and combine related actions into single tests.
While at it:
- use test_cmp instead of expr or test $foo = $bar, for more helpful
output with -v when tests fail;
- use test_commit for brevity.
Signed-off-by: Jonathan Nieder <redacted>
---
t/t6010-merge-base.sh | 317 ++++++++++++++++++++++++++-----------------------
1 files changed, 167 insertions(+), 150 deletions(-)
@@ -8,170 +8,187 @@ test_description='Merge base computation. ../test-lib.sh-T=$(gitwrite-tree)--M=1130000000-Z=+0000--GIT_COMMITTER_EMAIL=git@comm.iter.xz-GIT_COMMITTER_NAME='C O Mmiter'-GIT_AUTHOR_NAME='A U Thor'-GIT_AUTHOR_EMAIL=git@au.thor.xz-exportGIT_COMMITTER_EMAILGIT_COMMITTER_NAMEGIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL--doit(){-OFFSET=$1;shift-NAME=$1;shift-PARENTS=-forP-do-PARENTS="${PARENTS}-p $P "-done-GIT_COMMITTER_DATE="$(($M+$OFFSET))$Z"-GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE-exportGIT_COMMITTER_DATEGIT_AUTHOR_DATE-commit=$(echo$NAME|gitcommit-tree$T$PARENTS)-echo$commit>.git/refs/tags/$NAME-echo$commit-}--# E---D---C---B---A-# \'-_ \ \-# \ `---------G \-# \ \-# F----------------H--# Setup...-E=$(doit5E)-D=$(doit4D$E)-F=$(doit6F$E)-C=$(doit3C$D)-B=$(doit2B$C)-A=$(doit1A$B)-G=$(doit7G$B$E)-H=$(doit8H$A$F)--test_expect_success'compute merge-base (single)'\-'MB=$(gitmerge-baseGH)&&-expr"$(gitname-rev"$MB")":"[0-9a-f]* tags/B"'--test_expect_success'compute merge-base (all)'\-'MB=$(gitmerge-base--allGH)&&-expr"$(gitname-rev"$MB")":"[0-9a-f]* tags/B"'--test_expect_success'compute merge-base with show-branch'\-'MB=$(gitshow-branch--merge-baseGH)&&-expr"$(gitname-rev"$MB")":"[0-9a-f]* tags/B"'--# Setup for second test to demonstrate that relying on timestamps in a-# distributed SCM to provide a _consistent_ partial ordering of commits-# leads to insanity.-#-# Relative-# Structure timestamps-#-# PL PR +4 +4-# / \/ \ / \/ \-# L2 C2 R2 +3 -1 +3-# | | | | | |-# L1 C1 R1 +2 -2 +2-# | | | | | |-# L0 C0 R0 +1 -3 +1-# \ | / \ | /-# S 0-#-# The left and right chains of commits can be of any length and complexity as-# long as all of the timestamps are greater than that of S.--S=$(doit0S)--C0=$(doit-3C0$S)-C1=$(doit-2C1$C0)-C2=$(doit-1C2$C1)--L0=$(doit1L0$S)-L1=$(doit2L1$L0)-L2=$(doit3L2$L1)--R0=$(doit1R0$S)-R1=$(doit2R1$R0)-R2=$(doit3R2$R1)--PL=$(doit4PL$L2$C2)-PR=$(doit4PR$C2$R2)--test_expect_success'compute merge-base (single)'\-'MB=$(gitmerge-basePLPR)&&-expr"$(gitname-rev"$MB")":"[0-9a-f]* tags/C2"'--test_expect_success'compute merge-base (all)'\-'MB=$(gitmerge-base--allPLPR)&&-expr"$(gitname-rev"$MB")":"[0-9a-f]* tags/C2"'--# Another set to demonstrate base between one commit and a merge-# in the documentation.-#-# * C (MMC) * B (MMB) * A (MMA)-# * o * o * o-# * o * o * o-# * o * o * o-# * o | _______/-# | |/-# | * 1 (MM1)-# | _______/-# |/-# * root (MMR)-+test_expect_success'setup''+T=$(gitwrite-tree)&&++M=1130000000&&+Z=+0000&&++GIT_COMMITTER_EMAIL=git@comm.iter.xz&&+GIT_COMMITTER_NAME="C O Mmiter"&&+GIT_AUTHOR_NAME="A U Thor"&&+GIT_AUTHOR_EMAIL=git@au.thor.xz&&+exportGIT_COMMITTER_EMAILGIT_COMMITTER_NAMEGIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL&&++doit(){+OFFSET=$1&&+NAME=$2&&+shift2&&++PARENTS=&&+forP+do+PARENTS="${PARENTS}-p $P "+done&&++GIT_COMMITTER_DATE="$(($M+$OFFSET))$Z"&&+GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE&&+exportGIT_COMMITTER_DATEGIT_AUTHOR_DATE&&++commit=$(echo$NAME|gitcommit-tree$T$PARENTS)&&++echo$commit>.git/refs/tags/$NAME&&+echo$commit+}+'++test_expect_success'set up G and H''+# E---D---C---B---A+# \"-_ \ \+# \ `---------G \+# \ \+# F----------------H+E=$(doit5E)&&+D=$(doit4D$E)&&+F=$(doit6F$E)&&+C=$(doit3C$D)&&+B=$(doit2B$C)&&+A=$(doit1A$B)&&+G=$(doit7G$B$E)&&+H=$(doit8H$A$F)+'++test_expect_success'merge-base G H''+gitname-rev$B>expected&&++MB=$(gitmerge-baseGH)&&+gitname-rev"$MB">actual.single&&++MB=$(gitmerge-base--allGH)&&+gitname-rev"$MB">actual.all&&++MB=$(gitshow-branch--merge-baseGH)&&+gitname-rev"$MB">actual.sb&&++test_cmpexpectedactual.single&&+test_cmpexpectedactual.all&&+test_cmpexpectedactual.sb+'++test_expect_success'unsynchronized clocks''+# This test is to demonstrate that relying on timestamps in a distributed+# SCM to provide a _consistent_ partial ordering of commits leads to+# insanity.+#+# Relative+# Structure timestamps+#+# PL PR +4 +4+# / \/ \ / \/ \+# L2 C2 R2 +3 -1 +3+# | | | | | |+# L1 C1 R1 +2 -2 +2+# | | | | | |+# L0 C0 R0 +1 -3 +1+# \ | / \ | /+# S 0+#+# The left and right chains of commits can be of any length and complexity as+# long as all of the timestamps are greater than that of S.++S=$(doit0S)&&++C0=$(doit-3C0$S)&&+C1=$(doit-2C1$C0)&&+C2=$(doit-1C2$C1)&&++L0=$(doit1L0$S)&&+L1=$(doit2L1$L0)&&+L2=$(doit3L2$L1)&&++R0=$(doit1R0$S)&&+R1=$(doit2R1$R0)&&+R2=$(doit3R2$R1)&&++PL=$(doit4PL$L2$C2)&&+PR=$(doit4PR$C2$R2)++gitname-rev$C2>expected&&++MB=$(gitmerge-basePLPR)&&+gitname-rev"$MB">actual.single&&++MB=$(gitmerge-base--allPLPR)&&+gitname-rev"$MB">actual.all&&++test_cmpexpectedactual.single&&+test_cmpexpectedactual.all+' test_expect_success'merge-base for octopus-step (setup)''-test_tick&&gitcommit--allow-empty-mroot&&gittagMMR&&-test_tick&&gitcommit--allow-empty-m1&&gittagMM1&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mA&&gittagMMA&&+# Another set to demonstrate base between one commit and a merge+# in the documentation.+#+# * C (MMC) * B (MMB) * A (MMA)+# * o * o * o+# * o * o * o+# * o * o * o+# * o | _______/+# | |/+# | * 1 (MM1)+# | _______/+# |/+# * root (MMR)++test_commitMMR&&+test_commitMM1&&+test_commitMM-o&&+test_commitMM-p&&+test_commitMM-q&&+test_commitMMA&&gitcheckoutMM1&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mB&&gittagMMB&&+test_commitMM-r&&+test_commitMM-s&&+test_commitMM-t&&+test_commitMMB&&gitcheckoutMMR&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mC&&gittagMMC+test_commitMM-u&&+test_commitMM-v&&+test_commitMM-w&&+test_commitMM-x&&+test_commitMMC' test_expect_success'merge-base A B C''-MB=$(gitmerge-base--allMMAMMBMMC)&&-MM1=$(gitrev-parse--verifyMM1)&&-test"$MM1"="$MB"-'+gitrev-parse--verifyMM1>expected&&+gitrev-parse--verifyMMR>expected.sb&&++gitmerge-base--allMMAMMBMMC>actual&&+gitshow-branch--merge-baseMMAMMBMMC>actual.sb&&-test_expect_success'merge-base A B C using show-branch''-MB=$(gitshow-branch--merge-baseMMAMMBMMC)&&-MMR=$(gitrev-parse--verifyMMR)&&-test"$MMR"="$MB"+test_cmpexpectedactual&&+test_cmpexpected.sbactual.sb'-test_expect_success'criss-cross merge-base for octopus-step (setup)''+test_expect_success'criss-cross merge-base for octopus-step''gitreset--hardMMR&&-test_tick&&gitcommit--allow-empty-m1&&gittagCC1&&+test_commitCC1&&gitreset--hardE&&-test_tick&&gitcommit--allow-empty-m2&&gittagCC2&&-test_tick&&gitmerge-soursCC1&&-test_tick&&gitcommit--allow-empty-mo&&-test_tick&&gitcommit--allow-empty-mB&&gittagCCB&&+test_commitCC2&&+test_tick&&+gitmerge-soursCC1&&+test_commitCC-o&&+test_commitCCB&&gitreset--hardCC1&&-test_tick&&gitmerge-soursCC2&&-test_tick&&gitcommit--allow-empty-mA&&gittagCCA-'+gitmerge-soursCC2&&+test_commitCCA&&-test_expect_success'merge-base B A^^ A^^2''-MB0=$(gitmerge-base--allCCBCCA^^CCA^^2|sort)&&-MB1=$(gitrev-parseCC1CC2|sort)&&-test"$MB0"="$MB1"+gitrev-parseCC1CC2>expected&&+gitmerge-base--allCCBCCA^^CCA^^2>actual&&++sortexpected>expected.sorted&&+sortactual>actual.sorted&&+test_cmpexpected.sortedactual.sorted' test_done
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Guard setup with test_expect_success. Use test_might_fail
instead of ignoring the exit code from git config --unset.
Point out setup commands that are shared by multiple tests,
to make it easy to write GIT_SKIP_TESTS specifications that
work.
Signed-off-by: Jonathan Nieder <redacted>
---
t/t6200-fmt-merge-msg.sh | 278 ++++++++++++++++++++--------------------------
1 files changed, 119 insertions(+), 159 deletions(-)
@@ -70,14 +70,13 @@ test_expect_success setup 'i=$(($i+1))done&&-gitshow-branch+gitshow-branch&&++apos="'\''"'-cat>expected<<\EOF-Mergebranch'left'-EOF--test_expect_success'merge-msg test #1''+test_expect_success'message for merging local branch''+echo"Merge branch ${apos}left${apos}">expected&&gitcheckoutmaster&&gitfetch.left&&
@@ -86,11 +85,8 @@ test_expect_success 'merge-msg test #1' 'test_cmpexpectedactual'-cat>expected<<EOF-Mergebranch'left'of$(pwd)-EOF--test_expect_success'merge-msg test #2''+test_expect_success'message for merging external branch''+echo"Merge branch ${apos}left${apos} of $(pwd)">expected&&gitcheckoutmaster&&gitfetch"$(pwd)"left&&
@@ -99,139 +95,108 @@ test_expect_success 'merge-msg test #2' 'test_cmpexpectedactual'-cat>expected<<\EOF-Mergebranch'left'+test_expect_success'[merge] summary/log configuration''+cat>expected<<-EOF&&+Mergebranch${apos}left${apos}++*left:+Left#5+Left#4+Left#3+Common#2+Common#1+EOF-*left:-Left#5-Left#4-Left#3-Common#2-Common#1-EOF--test_expect_success'merge-msg test #3-1''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summarygitconfigmerge.logtrue&&+test_might_failgitconfig--unset-allmerge.summary&&gitcheckoutmaster&&test_tick&&gitfetch.left&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual-'+gitfmt-merge-msg<.git/FETCH_HEAD>actual1&&-test_expect_success'merge-msg test #3-2''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summarytrue&&gitcheckoutmaster&&test_tick&&gitfetch.left&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual-'+gitfmt-merge-msg<.git/FETCH_HEAD>actual2&&-cat>expected<<\EOF-Mergebranches'left'and'right'--*left:-Left#5-Left#4-Left#3-Common#2-Common#1--*right:-Right#5-Right#4-Right#3-Common#2-Common#1-EOF+test_cmpexpectedactual1&&+test_cmpexpectedactual2+'-test_expect_success'merge-msg test #4-1''+test_expect_success'setup: expected shortlog for two branches''+cat>expected<<-EOF+Mergebranches${apos}left${apos}and${apos}right${apos}++*left:+Left#5+Left#4+Left#3+Common#2+Common#1++*right:+Right#5+Right#4+Right#3+Common#2+Common#1+EOF+'-gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_expect_success'shortlog for two branches''gitconfigmerge.logtrue&&-+test_might_failgitconfig--unset-allmerge.summary&&gitcheckoutmaster&&test_tick&&gitfetch.leftright&&+gitfmt-merge-msg<.git/FETCH_HEAD>actual1&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual-'--test_expect_success'merge-msg test #4-2''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summarytrue&&-gitcheckoutmaster&&test_tick&&gitfetch.leftright&&+gitfmt-merge-msg<.git/FETCH_HEAD>actual2&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual-'--test_expect_success'merge-msg test #5-1''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summarygitconfigmerge.logyes&&-+test_might_failgitconfig--unset-allmerge.summary&&gitcheckoutmaster&&test_tick&&gitfetch.leftright&&+gitfmt-merge-msg<.git/FETCH_HEAD>actual3&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual-'--test_expect_success'merge-msg test #5-2''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&-gitcheckoutmaster&&test_tick&&gitfetch.leftright&&+gitfmt-merge-msg<.git/FETCH_HEAD>actual4&&-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&-test_cmpexpectedactual+test_cmpexpectedactual1&&+test_cmpexpectedactual2&&+test_cmpexpectedactual3&&+test_cmpexpectedactual4' test_expect_success'merge-msg -F''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&-gitcheckoutmaster&&test_tick&&gitfetch.leftright&&-gitfmt-merge-msg-F.git/FETCH_HEAD>actual&&test_cmpexpectedactual' test_expect_success'merge-msg -F in subdirectory''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&-gitcheckoutmaster&&test_tick&&gitfetch.leftright&&
@@ -245,11 +210,11 @@ test_expect_success 'merge-msg -F in subdirectory' '' test_expect_success'merge-msg with nothing to merge''--gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&+>empty&&+(cdremote&&gitcheckout-bunrelated&&
@@ -258,22 +223,20 @@ test_expect_success 'merge-msg with nothing to merge' 'gitfmt-merge-msg<.git/FETCH_HEAD>../actual)&&-test_cmp/dev/nullactual+test_cmpemptyactual'-cat>expected<<\EOF-Mergetag'tag-r3'--*tag'tag-r3':-Right#3-Common#2-Common#1-EOF- test_expect_success'merge-msg tag''+cat>expected<<-EOF&&+Mergetag${apos}tag-r3${apos}-gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+*tag${apos}tag-r3${apos}:+Right#3+Common#2+Common#1+EOF++test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&gitcheckoutmaster&&
@@ -314,26 +275,24 @@ test_expect_success 'merge-msg two tags' 'test_cmpexpectedactual'-cat>expected<<\EOF-Mergebranch'left',tag'tag-r3'--*tag'tag-r3':-Right#3-Common#2-Common#1--*left:-Left#5-Left#4-Left#3-Common#2-Common#1-EOF- test_expect_success'merge-msg tag and branch''+cat>expected<<-EOF&&+Mergebranch${apos}left${apos},tag${apos}tag-r3${apos}-gitconfig--unset-allmerge.log-gitconfig--unset-allmerge.summary+*tag${apos}tag-r3${apos}:+Right#3+Common#2+Common#1++*left:+Left#5+Left#4+Left#3+Common#2+Common#1+EOF++test_might_failgitconfig--unset-allmerge.log&&gitconfigmerge.summaryyes&&gitcheckoutmaster&&
@@ -344,26 +303,27 @@ test_expect_success 'merge-msg tag and branch' 'test_cmpexpectedactual'-cat>expected<<\EOF-Mergebranch'long'--*long:(35commits)-EOF- test_expect_success'merge-msg lots of commits''+{+cat<<-EOF&&+Mergebranch${apos}long${apos}++*long:(35commits)+EOF++i=29&&+whiletest$i-gt9+do+echo" $i"&&+i=$(($i-1))+done&&+echo" ..."+}>expected&&gitcheckoutmaster&&test_tick&&gitfetch.long&&-i=29&&-whiletest$i-gt9-do-echo" $i"&&-i=$(($i-1))-done>>expected&&-echo" ...">>expected-gitfmt-merge-msg<.git/FETCH_HEAD>actual&&test_cmpexpectedactual'
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
For example, a person reading the merge-base man page might wonder
about the fastest way to check if one commit is an ancestor of
another (which would require rev-list).
Signed-off-by: Jonathan Nieder <redacted>
---
Documentation/git-merge-base.txt | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
@@ -96,6 +96,12 @@ Documentation -------------- Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.+See also+--------+linkgit:git-rev-list[1],+linkgit:git-show-branch[1],+linkgit:git-merge[1]+ GIT --- Part of the linkgit:git[1] suite
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
While show-branch --merge-base does not support more than MAX_REVS
revs, git supports more with a different algorithm
(v1.6.0-rc0~51^2~13, Introduce get_octopus_merge_bases() in commit.c,
2008-06-27). Expose that functionality.
This should help scripts to catch up with builtin merge in supporting
dodecapus.
Signed-off-by: Jonathan Nieder <redacted>
---
Documentation/git-merge-base.txt | 19 ++++++++++++-------
builtin/merge-base.c | 35 ++++++++++++++++++++++++++++++++---
t/t6010-merge-base.sh | 2 ++
3 files changed, 46 insertions(+), 10 deletions(-)
@@ -8,7 +8,7 @@ git-merge-base - Find as good common ancestors as possible for a merge SYNOPSIS ---------'git merge-base' [-a|--all] <commit> <commit>...+'git merge-base' [-a|--all] [--octopus] <commit> <commit>... DESCRIPTION -----------
@@ -20,12 +20,12 @@ that does not have any better common ancestor is a 'best common ancestor', i.e. a 'merge base'. Note that there can be more than one merge base for a pair of commits.-Among the two commits to compute the merge base from, one is specified by-the first commit argument on the command line; the other commit is a-(possibly hypothetical) commit that is a merge across all the remaining-commits on the command line. As the most common special case, specifying only-two commits on the command line means computing the merge base between-the given two commits.+Unless `--octopus` is given, among the two commits to compute the merge+base from, one is specified by the first commit argument on the command+line; the other commit is a (possibly hypothetical) commit that is a merge+across all the remaining commits on the command line. As the most common+special case, specifying only two commits on the command line means+computing the merge base between the given two commits. As a consequence, the 'merge base' is not necessarily contained in each of the commit arguments if more than two commits are specified. This is different
@@ -37,6 +37,11 @@ OPTIONS --all:: Output all merge bases for the commits, instead of just one.+--octopus::+ Compute the best common ancestors of all supplied commits,+ in preparation for an n-way merge. This mimics the behavior+ of 'git show-branch --merge-base'.+ DISCUSSION ----------
@@ -23,7 +23,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)}staticconstchar*constmerge_base_usage[]={-"git merge-base [-a|--all] <commit> <commit>...",+"git merge-base [-a|--all] [--octopus] <commit> <commit>...",NULL};
@@ -41,21 +41,50 @@ static struct commit *get_commit_reference(const char *arg)returnr;}+staticintshow_octopus_merge_bases(intcount,constchar**args,intshow_all)+{+structcommit_list*revs=NULL;+structcommit_list*result;+inti;++for(i=count-1;i>=0;i++)+commit_list_insert(get_commit_reference(args[i]),&revs);+result=get_octopus_merge_bases(revs);++if(!result)+return1;++while(result){+printf("%s\n",sha1_to_hex(result->item->object.sha1));+if(!show_all)+return0;+result=result->next;+}++return0;+}+intcmd_merge_base(intargc,constchar**argv,constchar*prefix){structcommit**rev;intrev_nr=0;intshow_all=0;+intoctopus=0;structoptionoptions[]={-OPT_BOOLEAN('a',"all",&show_all,"outputs all common ancestors"),+OPT_BOOLEAN('a',"all",&show_all,"output all common ancestors"),+OPT_BOOLEAN(0,"octopus",&octopus,"find ancestors for a single n-way merge"),OPT_END()};git_config(git_default_config,NULL);argc=parse_options(argc,argv,prefix,options,merge_base_usage,0);-if(argc<2)+if(!octopus&&argc<2)usage_with_options(merge_base_usage,options);++if(octopus)+returnshow_octopus_merge_bases(argc,argv,show_all);+rev=xmalloc(argc*sizeof(*rev));while(argc-->0)rev[rev_nr++]=get_commit_reference(*argv++);
@@ -164,9 +164,11 @@ test_expect_success 'merge-base A B C' 'gitrev-parse--verifyMMR>expected.sb&&gitmerge-base--allMMAMMBMMC>actual&&+gitmerge-base--all--octopusMMAMMBMMC>actual.common&&gitshow-branch--merge-baseMMAMMBMMC>actual.sb&&test_cmpexpectedactual&&+test_cmpexpected.sbactual.common&&test_cmpexpected.sbactual.sb'
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
While show-branch --independent does not support more than MAX_REVS
revs, git internally supports more with a different algorithm.
Expose that functionality as "git merge-base --independent".
This should help scripts to catch up with builtin merge in supporting
dodecapus.
Signed-off-by: Jonathan Nieder <redacted>
---
Documentation/git-merge-base.txt | 9 ++++++++
builtin/merge-base.c | 21 ++++++++++++++-----
t/t6010-merge-base.sh | 39 +++++++++++++++++++++++++++++++++++++-
3 files changed, 62 insertions(+), 7 deletions(-)
@@ -8,7 +8,9 @@ git-merge-base - Find as good common ancestors as possible for a merge SYNOPSIS --------+[verse] 'git merge-base' [-a|--all] [--octopus] <commit> <commit>...+'git merge-base' --independent <commit>... DESCRIPTION -----------
@@ -42,6 +44,13 @@ OPTIONS in preparation for an n-way merge. This mimics the behavior of 'git show-branch --merge-base'.+--independent::+ Instead of printing merge bases, print a minimal subset of+ the supplied commits with the same ancestors. In other words,+ among the commits given, list those which cannot be reached+ from any other. This mimics the behavior of 'git show-branch+ --independent'.+ DISCUSSION ----------
@@ -70,20 +75,24 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)intrev_nr=0;intshow_all=0;intoctopus=0;+intreduce=0;structoptionoptions[]={OPT_BOOLEAN('a',"all",&show_all,"output all common ancestors"),OPT_BOOLEAN(0,"octopus",&octopus,"find ancestors for a single n-way merge"),+OPT_BOOLEAN(0,"independent",&reduce,"list revs not reachable from others"),OPT_END()};git_config(git_default_config,NULL);argc=parse_options(argc,argv,prefix,options,merge_base_usage,0);-if(!octopus&&argc<2)+if(!octopus&&!reduce&&argc<2)usage_with_options(merge_base_usage,options);+if(reduce&&(show_all||octopus))+die("--independent cannot be used with other options");-if(octopus)-returnshow_octopus_merge_bases(argc,argv,show_all);+if(octopus||reduce)+returnhandle_octopus(argc,argv,reduce,show_all);rev=xmalloc(argc*sizeof(*rev));while(argc-->0)
@@ -3,7 +3,7 @@# Copyright (c) 2005 Junio C Hamano#-test_description='Mergebasecomputation.+test_description='Mergebaseandparentlistcomputation.' ../test-lib.sh
@@ -75,6 +75,26 @@ test_expect_success 'merge-base G H' 'test_cmpexpectedactual.sb'+test_expect_success'merge-base/show-branch --independent''+gitname-rev"$H">expected1&&+gitname-rev"$H""$G">expected2&&++parents=$(gitmerge-base--independentH)&&+gitname-rev$parents>actual1.mb&&+parents=$(gitmerge-base--independentAHG)&&+gitname-rev$parents>actual2.mb&&++parents=$(gitshow-branch--independentH)&&+gitname-rev$parents>actual1.sb&&+parents=$(gitshow-branch--independentAHG)&&+gitname-rev$parents>actual2.sb&&++test_cmpexpected1actual1.mb&&+test_cmpexpected2actual2.mb&&+test_cmpexpected1actual1.sb&&+test_cmpexpected2actual2.sb+'+ test_expect_success'unsynchronized clocks''# This test is to demonstrate that relying on timestamps in a distributed# SCM to provide a _consistent_ partial ordering of commits leads to
@@ -125,6 +145,23 @@ test_expect_success 'unsynchronized clocks' 'test_cmpexpectedactual.all'+test_expect_success'--independent with unsynchronized clocks''+IB=$(doit0IB)&&+I1=$(doit-10I1$IB)&&+I2=$(doit-9I2$I1)&&+I3=$(doit-8I3$I2)&&+I4=$(doit-7I4$I3)&&+I5=$(doit-6I5$I4)&&+I6=$(doit-5I6$I5)&&+I7=$(doit-4I7$I6)&&+I8=$(doit-3I8$I7)&&+IH=$(doit-2IH$I8)&&++echo$IH>expected&&+gitmerge-base--independentIBIH>actual&&+test_cmpexpectedactual+'+ test_expect_success'merge-base for octopus-step (setup)''# Another set to demonstrate base between one commit and a merge# in the documentation.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
The fmt-merge-msg backend has supported a custom subject line and
message beginning since v1.7.1.1~23^2 (merge: --log appends shortlog
to message if specified, 2010-05-11). Expose the functionality for
scripted callers.
Cc: Tay Ray Chuan <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Documentation/git-fmt-merge-msg.txt | 9 +++++++--
builtin/fmt-merge-msg.c | 18 ++++++++++++++++--
t/t6200-fmt-merge-msg.sh | 32 ++++++++++++++++++++++++++++++++
3 files changed, 55 insertions(+), 4 deletions(-)
@@ -38,6 +38,11 @@ OPTIONS Synonyms to --log and --no-log; these are deprecated and will be removed in the future.+-m <subject>::+--message <subject>::+ Use <subject> instead of the branch names for the first line+ of the log message. For use with `--log`.+ -F <file>:: --file <file>:: Take the list of merged objects from <file> instead of
@@ -319,11 +319,14 @@ int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out) {intcmd_fmt_merge_msg(intargc,constchar**argv,constchar*prefix){constchar*inpath=NULL;+constchar*oneline_msg=NULL;structoptionoptions[]={OPT_BOOLEAN(0,"log",&merge_summary,"populate log with the shortlog"),{OPTION_BOOLEAN,0,"summary",&merge_summary,NULL,"alias for --log (deprecated)",PARSE_OPT_NOARG|PARSE_OPT_HIDDEN},+OPT_STRING('m',"message",&oneline_msg,"oneline",+"use <oneline> as subject line"),OPT_FILENAME('F',"file",&inpath,"file to read from"),OPT_END()};
@@ -129,6 +129,38 @@ test_expect_success '[merge] summary/log configuration' 'test_cmpexpectedactual2'+test_expect_success'fmt-merge-msg -m''+echo"Sync with left">expected&&+cat>expected.log<<-EOF&&+Syncwithleft++*${apos}left${apos}of$(pwd):+Left#5+Left#4+Left#3+Common#2+Common#1+EOF++test_might_failgitconfig--unsetmerge.log&&+test_might_failgitconfig--unsetmerge.summary&&+gitcheckoutmaster&&+gitfetch"$(pwd)"left&&+gitfmt-merge-msg-m"Sync with left"<.git/FETCH_HEAD>actual&&+gitfmt-merge-msg--log-m"Sync with left"\+<.git/FETCH_HEAD>actual.log&&+gitconfigmerge.logtrue&&+gitfmt-merge-msg-m"Sync with left"\+<.git/FETCH_HEAD>actual.log-config&&+gitfmt-merge-msg--no-log-m"Sync with left"\+<.git/FETCH_HEAD>actual.nolog&&++test_cmpexpectedactual&&+test_cmpexpected.logactual.log&&+test_cmpexpected.logactual.log-config&&+test_cmpexpectedactual.nolog+'+ test_expect_success'setup: expected shortlog for two branches''cat>expected<<-EOFMergebranches${apos}left${apos}and${apos}right${apos}
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Port v1.6.1-rc1~319 (provide more errors for the "merge into empty
head" case, 2008-08-21) to the example merge script.
Noticed by comparison with builtin merge.
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
@@ -245,6 +245,10 @@ thenexit1fi+test"$squash"!=t||+die"Squash commit into empty head not supported yet"+test"$allow_fast_forward"=t||+die"Non-fast-forward into an empty head does not make sense"rh=$(gitrev-parse--verify"$1^0")||die"$1 - not something we can merge"
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Before:
You are in the middle of a conflicted merge.
After:
Merge is not possible because you have unmerged files.
I prefer the old message, but the new one is more consistent with
other commands and tests expect it. In particular, without this
change the scripted merge does not pass t3030.
Based on v1.7.0-rc0~66^2 (Be more user-friendly when refusing to do
something because of conflict., 2010-01-12).
Cc: Matthieu Moy <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
@@ -25,7 +25,7 @@ require_work_tree cd_to_topleveltest-z"$(gitls-files-u)"||-die"You are in the middle of a conflicted merge."+die"Merge is not possible because you have unmerged files."LF=''
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Check MERGE_HEAD and bail out if it exists. Based on v1.6.3.3~3^2
(refuse to merge during a merge, 2009-06-01). Without this change,
the scripted merge does not pass t3030.
Cc: Clemens Buchacher <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
@@ -27,6 +27,9 @@ cd_to_topleveltest-z"$(gitls-files-u)"||die"Merge is not possible because you have unmerged files."+!test-e"$GIT_DIR/MERGE_HEAD"||+die'You have not concluded your merge (MERGE_HEAD exists).'+LF=''
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
- point out remote-tracking branches as "remote branch
'upstream/master'";
- avoid misleading log messages when a tag and branch
share a name.
This approximates the builtin merge command's behavior well
enough to pass the relevant tests.
Based roughly on v1.6.4.2~10^2 (merge: indicate remote tracking
branches in merge message, 2009-08-09) and v1.6.4.2~10^2~1 (merge: fix
incorrect merge message for ambiguous tag/branch, 2009-08-09).
Cc: Jeff King <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 27 +++++++++++++++++++--------
1 files changed, 19 insertions(+), 8 deletions(-)
@@ -16,6 +16,7 @@ squash create a single commit instead of doing a merge commitperformacommitifthemergesucceeds(default) ffallowfast-forward(default) s,strategy=mergestrategytouse+X=optionforselectedmergestrategy m,message=messagetobeusedforthemergecommit(ifany)"
@@ -469,7 +475,7 @@ do# Remember which strategy left the state in the working treewt_strategy=$strategy-git-merge-$strategy$common--"$head_arg""$@"+eval'git-merge-$strategy '"$xopt"' $common -- "$head_arg" "$@"'exit=$?iftest"$no_commit"=t&&test"$exit"=0then
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
The idea comes from v1.6.1-rc1~294^2~7 (builtin-merge: allow using a
custom strategy, 2008-07-30).
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Some git-merge-* commands are not merge strategies. This is based on
v1.6.1-rc1~294^2~7 (builtin-merge: allow using a custom strategy,
2008-07-30) but it is less smart: we just use a hard-coded list of
forbidden strategy names. It is okay if this falls out of date, since
the code is just an example.
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Based on v1.7.1.1~23^2 (merge: --log appends shortlog to message if
specified, 2010-05-11). Without this change, the scripted
(non-builtin) merge does not pass t7604.
Cc: Tay Ray Chuan <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
@@ -294,12 +294,18 @@ else# the given message. If remote is invalid we will die# later in the common codepath so we discard the error# in this loop.-merge_name=$(forremote+merge_msg="$(+forremotedomerge_name"$remote"-done|gitfmt-merge-msg$log_arg-)-merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"+done|+iftest"$have_message"=t+then+gitfmt-merge-msg-m"$merge_msg"$log_arg+else+gitfmt-merge-msg$log_arg+fi+)"fihead=$(gitrev-parse--verify"$head_arg"^0)||usage
@@ -374,7 +374,7 @@ case "$#" incommon=$(gitmerge-base--all$head"$@");; *)-common=$(gitshow-branch--merge-base$head"$@")+common=$(gitmerge-base--all--octopus$head"$@");;esacecho"$head">"$GIT_DIR/ORIG_HEAD"
@@ -528,9 +528,9 @@ if test '' != "$result_tree"theniftest"$allow_fast_forward"="t"then-parents=$(gitshow-branch--independent"$head""$@")+parents=$(gitmerge-base--independent"$head""$@")else-parents=$(gitrev-parse"$head""$@")+parents=$(gitrev-parse"$head""$@")fiparents=$(echo"$parents"|sed-e's/^/-p /')result_commit=$(printf'%s\n'"$merge_msg"|gitcommit-tree$result_tree$parents)||exit
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Port v1.6.6-rc0~62^2 (Teach 'git merge' and 'git pull' the option
--ff-only, 2009-10-29) to the old merge script.
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 17 +++++++++++++++--
1 files changed, 15 insertions(+), 2 deletions(-)
@@ -189,7 +191,13 @@ parse_config () {--no-ff)test"$squash"!=t||die"You cannot combine --squash with --no-ff."+test"$fast_forward_only"!=t||+die"You cannot combine --ff-only with --no-ff."allow_fast_forward=f;;+--ff-only)+test"$allow_fast_forward"!=f||+die"You cannot combine --ff-only with --no-ff."+fast_forward_only=t;;-s|--strategy)shiftcase" $all_strategies "in
@@ -412,8 +420,8 @@ t,1,"$head",*)# We are not doing octopus, not fast-forward, and have only# one common.gitupdate-index--refresh2>/dev/null-case"$allow_trivial_merge"in-t)+case"$allow_trivial_merge,$fast_forward_only"in+t,)# See if it is really trivial.gitvarGIT_COMMITTER_IDENT>/dev/null||exitecho"Trying really trivial in-index merge..."
@@ -452,6 +460,11 @@ t,1,"$head",*);;esac+iftest"$fast_forward_only"=t+then+die"Not possible to fast-forward, aborting."+fi+# We are going to make a new commit. gitvarGIT_COMMITTER_IDENT>/dev/null||exit
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
In a --no-ff merge with conflicts, "git commit" used to forget the
--no-ff when used to complete the merge. That was fixed by
v1.6.1-rc1~134^2 (builtin-commit: use reduce_heads() only when
appropriate, 2008-10-03) for the builtin merge. Port the change to
the merge script in contrib/examples.
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
@@ -585,7 +585,15 @@ elsedoecho$remotedone>"$GIT_DIR/MERGE_HEAD"-printf'%s\n'"$merge_msg">"$GIT_DIR/MERGE_MSG"+printf'%s\n'"$merge_msg">"$GIT_DIR/MERGE_MSG"||+die"Could not write to $GIT_DIR/MERGE_MSG"+iftest"$allow_fast_forward"!=t+then+printf"%s"no-ff+else+:+fi>"$GIT_DIR/MERGE_MODE"||+die"Could not write to $GIT_DIR/MERGE_MODE"fiiftest"$merge_was_ok"=t
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Port v1.6.2-rc1~10^2 (Teach @{-1} to git merge, 2009-02-13) to
the old merge script.
Signed-off-by: Jonathan Nieder <redacted>
---
contrib/examples/git-merge.sh | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:19
Port v1.7.0-rc0~83^2 (Teach --[no-]rerere-autoupdate option to
merge, revert and friends, 2009-12-04) to the example merge script.
After this change, all tests pass for me with the scripted
merge.
Signed-off-by: Jonathan Nieder <redacted>
---
To test: remove cmd_merge from the builtins list in git.c,
build git, and then run:
cp contrib/examples/git-merge.sh .
make SCRIPT_SH=git-merge.sh git-merge
cd t && make
That's the end of the series. Thanks for reading.
contrib/examples/git-merge.sh | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
@@ -16,6 +16,7 @@ squash create a single commit instead of doing a merge commitperformacommitifthemergesucceeds(default) ffallowfast-forward(default) ff-onlyabortiffast-forwardisnotpossible+rerere-autoupdateupdateindexwithanyreusedconflictresolution s,strategy=mergestrategytouseX=optionforselectedmergestrategy m,message=messagetobeusedforthemergecommit(ifany)
On Tue, Aug 17, 2010 at 06:54, Jonathan Nieder [off-list ref] wrote:
Probably as a development aid, this test script runs gitk --all
to allow the driver to inspect history between tests when run
with --debug. As a result, running all tests with --debug
requires closing a long series of gitk displays, one at a time.
Yes!, I was going to fix that myself sometime. Thanks for doing it,
that behavior was very annoying.
On Tue, Aug 17, 2010 at 06:51, Jonathan Nieder [off-list ref] wrote:
While preparing to make some minor "git merge" changes, I noticed that
the old merge script does not pass all tests any more. Since it can
be easier to prototype in shell and then port to C, I think that is
worth fixing.
Of course this is not urgent at all.
Patches 2-7 are minor test changes. They are early in the series
to give flexibility about when to merge them.
Those all looked good, thanks for tackling that.
Patches 8-10 expose functionality used by merge when handling octopus
merges.
You mean 9-10, 8 looks good. I don't have the familiarity to comment
on 9-10.
Patches 12 and later are ports of various patches to builtin/merge.c.
I did the bare minimum to make tests pass. :)
Those also look good to my untrained eye.
How do you run the tests against git-merge.sh? Is there some make
target to use it instead of git-merge.c, or do you manually move it in
place?
If it's the latter a switch somewhere to run the test suite against
these .sh alternatives might compliment this series nicely.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:20
Ævar Arnfjörð Bjarmason wrote:
On Tue, Aug 17, 2010 at 06:51, Jonathan Nieder [off-list ref] wrote:
quoted
Patches 8-10 expose functionality used by merge when handling octopus
merges.
You mean 9-10, 8 looks good. I don't have the familiarity to comment
on 9-10.
I would be especially interested in feedback on the interface from
those two. ;-)
Is merge-base the right command to learn --independent?
Is --independent the right name for "reduced parent list"?
Is merge-base --octopus generally useful at all, or should we change
the API for custom octopus strategies (maybe at the same time as
teaching them to declare NO_TRIVIAL and NO_FAST_FORWARD preferences)
to leave the list of merge bases out?
quoted
Patches 12 and later are ports of various patches to builtin/merge.c.
I did the bare minimum to make tests pass. :)
Those also look good to my untrained eye.
Thanks for looking them over.
How do you run the tests against git-merge.sh? Is there some make
target to use it instead of git-merge.c, or do you manually move it in
place?
Ah, yes, I should have made that information more prominent.
To test: remove cmd_merge from the builtins list in git.c,
build git, and then run:
cp contrib/examples/git-merge.sh .
make SCRIPT_SH=git-merge.sh git-merge
cd t && make
If it's the latter a switch somewhere to run the test suite against
these .sh alternatives might compliment this series nicely.
Yes, that sounds like an good idea. Of course most of the retired
scripts are bitrotted by now.
From: Tay Ray Chuan <hidden> Date: 2016-06-15 22:49:20
On Tue, Aug 17, 2010 at 3:06 PM, Jonathan Nieder [off-list ref] wrote:
Based on v1.7.1.1~23^2 (merge: --log appends shortlog to message if
specified, 2010-05-11). Without this change, the scripted
(non-builtin) merge does not pass t7604.
Cc: Tay Ray Chuan <redacted>
Signed-off-by: Jonathan Nieder <redacted>
# the given message. If remote is invalid we will die
# later in the common codepath so we discard the error
# in this loop.
- merge_name=$(for remote
+ merge_msg="$(
+ for remote
do
merge_name "$remote"
- done | git fmt-merge-msg $log_arg
- )
- merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
+ done |
+ if test "$have_message" = t
+ then
+ git fmt-merge-msg -m "$merge_msg" $log_arg
hmm, when did git-fmt-merge-msg learn -m? Mine (1.7.2.1.219.gf2a27) doesn't.
--
Cheers,
Ray Chuan
Really? Why can't you stuff the command to execute in a variable? On
that note, why wasn't that done in the first place?! This kind of
repetition is not very DRY.
--
Cheers,
Sverre Rabbelier
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:20
Since v1.7.1.1~23^2 (merge: --log appends shortlog to message if
specified, 2010-05-11), the fmt-merge-msg backend supports custom text
to override the merge title "Merge <foo> into <bar>".
Expose this functionality for scripted callers. Example:
git fmt-merge-msg --log -m \
"$(printf '%s\n' \
"Merge branch 'api-cleanup' into feature" \
'' \
'This is to use a few functions refactored for this purpose.'
)" <.git/FETCH_HEAD
Cc: Tay Ray Chuan <redacted>
Signed-off-by: Jonathan Nieder <redacted>
---
Jonathan Nieder wrote:
@@ -38,6 +38,11 @@ OPTIONS Synonyms to --log and --no-log; these are deprecated and will be removed in the future.+-m <message>::+--message <message>::+ Use <message> instead of the branch names for the first line+ of the log message. For use with `--log`.+ -F <file>:: --file <file>:: Take the list of merged objects from <file> instead of
@@ -319,11 +319,14 @@ int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out) {intcmd_fmt_merge_msg(intargc,constchar**argv,constchar*prefix){constchar*inpath=NULL;+constchar*message=NULL;structoptionoptions[]={OPT_BOOLEAN(0,"log",&merge_summary,"populate log with the shortlog"),{OPTION_BOOLEAN,0,"summary",&merge_summary,NULL,"alias for --log (deprecated)",PARSE_OPT_NOARG|PARSE_OPT_HIDDEN},+OPT_STRING('m',"message",&message,"text",+"use <text> as start of message"),OPT_FILENAME('F',"file",&inpath,"file to read from"),OPT_END()};
@@ -129,6 +129,38 @@ test_expect_success '[merge] summary/log configuration' 'test_cmpexpectedactual2'+test_expect_success'fmt-merge-msg -m''+echo"Sync with left">expected&&+cat>expected.log<<-EOF&&+Syncwithleft++*${apos}left${apos}of$(pwd):+Left#5+Left#4+Left#3+Common#2+Common#1+EOF++test_might_failgitconfig--unsetmerge.log&&+test_might_failgitconfig--unsetmerge.summary&&+gitcheckoutmaster&&+gitfetch"$(pwd)"left&&+gitfmt-merge-msg-m"Sync with left"<.git/FETCH_HEAD>actual&&+gitfmt-merge-msg--log-m"Sync with left"\+<.git/FETCH_HEAD>actual.log&&+gitconfigmerge.logtrue&&+gitfmt-merge-msg-m"Sync with left"\+<.git/FETCH_HEAD>actual.log-config&&+gitfmt-merge-msg--no-log-m"Sync with left"\+<.git/FETCH_HEAD>actual.nolog&&++test_cmpexpectedactual&&+test_cmpexpected.logactual.log&&+test_cmpexpected.logactual.log-config&&+test_cmpexpectedactual.nolog+'+ test_expect_success'setup: expected shortlog for two branches''cat>expected<<-EOFMergebranches${apos}left${apos}and${apos}right${apos}
Really? Why can't you stuff the command to execute in a variable? On
that note, why wasn't that done in the first place?! This kind of
repetition is not very DRY.
My thought was that
test_debug '$debug_command'
...
test_debug '$debug_command'
...
[etc]
is not very DRY either, so I am hoping some configurable version of
-- 8< --
appears to replace it. In the short term, the "s/gitk --all/git log
--graph --decorate --oneline --all/" was just meant as a quick fix
so as not to drop the feature. Ideas?
Really? Why can't you stuff the command to execute in a variable? On
that note, why wasn't that done in the first place?! This kind of
repetition is not very DRY.
My thought was that
test_debug '$debug_command'
...
test_debug '$debug_command'
...
[etc]
is not very DRY either, so I am hoping some configurable version of
-- 8< --
if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
echo ""
fi
+ test_debug "git log --graph --decorate --oneline --all"
return 0
}
-- >8 --
appears to replace it. In the short term, the "s/gitk --all/git log
--graph --decorate --oneline --all/" was just meant as a quick fix
so as not to drop the feature. Ideas?
The main issue here is that --debug means two things. It runs
test_debug() code AND instructs the test-lib not to remove the trash
directory when it's done.
If we had a separate --keep-trash option most of this problem would go
away, no?
Aside from that it's better to use git log rather than gitk in
test_debug, since it's in text form it can be easily sent along with a
failing test, which is not the case for dozens of gitk invocations.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:49:20
Ævar Arnfjörð Bjarmason wrote:
The main issue here is that --debug means two things. It runs
test_debug() code AND instructs the test-lib not to remove the trash
directory when it's done.
Most of the time I use --immediate, insert an explicit "exit", or hit
^C instead of waiting for the test to complete anyway. --debug always
struck me as a theoretically useful thing (more useful output!) though
I never used it much.
If we had a separate --keep-trash option most of this problem would go
away, no?
That might be useful for e.g. automatically re-running tests with
expected failures or unexpected successes and tarring up the test
repo.
Aside from that it's better to use git log rather than gitk in
test_debug, since it's in text form it can be easily sent along with a
failing test, which is not the case for dozens of gitk invocations.
Right, the effect of this patch is good though I agree with Sverre
that its method is ugly.
Maybe unconditionally printing a log between tests would be good
behavior for --debug after all. Not sure.