* [PATCH] Add --ff-only flag to git-merge @ 2009-01-28 12:53 Yuval Kogman 2009-01-28 13:26 ` Johannes Schindelin ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Yuval Kogman @ 2009-01-28 12:53 UTC (permalink / raw) To: git; +Cc: Yuval Kogman This patch adds an --ff-only flag to git-merge. When specified git-merge will exit with an error whenver a merge will not be a simple fast forward, similar to the default behavior of git push. --- builtin-merge.c | 6 ++++++ t/t7600-merge.sh | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 0 deletions(-) diff --git a/builtin-merge.c b/builtin-merge.c index e4555b0..d37423b 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -44,6 +44,7 @@ static const char * const builtin_merge_usage[] = { static int show_diffstat = 1, option_log, squash; static int option_commit = 1, allow_fast_forward = 1; static int allow_trivial = 1, have_message; +static int only_fast_forward; static struct strbuf merge_msg; static struct commit_list *remoteheads; static unsigned char head[20], stash[20]; @@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = { "perform a commit if the merge succeeds (default)"), OPT_BOOLEAN(0, "ff", &allow_fast_forward, "allow fast forward (default)"), + OPT_BOOLEAN(0, "ff-only", &only_fast_forward, + "allow only fast forward"), OPT_CALLBACK('s', "strategy", &use_strategies, "strategy", "merge strategy to use", option_parse_strategy), OPT_CALLBACK('m', "message", &merge_msg, "message", @@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) finish(o->sha1, msg.buf); drop_save(); return 0; + } else if ( only_fast_forward ) { + printf("Merge is non fast forward, aborting.\n"); + return 1; } else if (!remoteheads->next && common->next) ; /* diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index e5b210b..6c2febc 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -234,6 +234,8 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' ' test_must_fail git merge -s index c1 ' +test_debug 'gitk --all' + test_expect_success 'merge c0 with c1' ' git reset --hard c0 && git merge c1 && @@ -243,6 +245,15 @@ test_expect_success 'merge c0 with c1' ' test_debug 'gitk --all' +test_expect_success 'merge c0 with c1 (fast forward only)' ' + git reset --hard c0 && + git merge --ff-only c1 && + verify_merge file result.1 && + verify_head "$c1" +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c2' ' git reset --hard c1 && test_tick && @@ -253,6 +264,14 @@ test_expect_success 'merge c1 with c2' ' test_debug 'gitk --all' +test_expect_success 'merge c1 with c2' ' + git reset --hard c1 && + test_tick && + test_must_fail git merge --ff-only c2 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c2 and c3' ' git reset --hard c1 && test_tick && @@ -263,6 +282,14 @@ test_expect_success 'merge c1 with c2 and c3' ' test_debug 'gitk --all' +test_expect_success 'merge c1 with c2 and c3 (fast forward only' ' + git reset --hard c1 && + test_tick && + test_must_fail git merge --ff-only c2 c3 +' + +test_debug 'gitk --all' + test_expect_success 'merge c0 with c1 (no-commit)' ' git reset --hard c0 && git merge --no-commit c1 && @@ -470,6 +497,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' test_debug 'gitk --all' +test_expect_success 'merge fast forward only' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + test_must_fail git merge --ff-only c0 c2 c0 c1 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c0, c2, c0, and c1' ' git reset --hard c1 && git config branch.master.mergeoptions "" && @@ -481,6 +517,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' test_debug 'gitk --all' +test_expect_success 'merge fast forward only' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + test_must_fail git merge --ff-only c1 c2 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c1 and c2' ' git reset --hard c1 && git config branch.master.mergeoptions "" && -- 1.6.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-28 12:53 [PATCH] Add --ff-only flag to git-merge Yuval Kogman @ 2009-01-28 13:26 ` Johannes Schindelin 2009-01-28 13:29 ` Yuval Kogman 2009-01-28 14:35 ` Sverre Rabbelier 2009-01-28 21:12 ` Junio C Hamano 2 siblings, 1 reply; 9+ messages in thread From: Johannes Schindelin @ 2009-01-28 13:26 UTC (permalink / raw) To: Yuval Kogman; +Cc: git Hi, On Wed, 28 Jan 2009, Yuval Kogman wrote: > @@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) > finish(o->sha1, msg.buf); > drop_save(); > return 0; > + } else if ( only_fast_forward ) { > + printf("Merge is non fast forward, aborting.\n"); > + return 1; > } else if (!remoteheads->next && common->next) If you compare the two if() lines, you will see that you mixed style. Ciao, Dscho ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-28 13:26 ` Johannes Schindelin @ 2009-01-28 13:29 ` Yuval Kogman 0 siblings, 0 replies; 9+ messages in thread From: Yuval Kogman @ 2009-01-28 13:29 UTC (permalink / raw) To: Johannes Schindelin; +Cc: git 2009/1/28 Johannes Schindelin <Johannes.Schindelin@gmx.de>: > If you compare the two if() lines, you will see that you mixed style. Thanks, I will be fixing it here: http://github.com/nothingmuch/git/tree/ff-only before I send a new version, as I likely screwed up many things, not just that =) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-28 12:53 [PATCH] Add --ff-only flag to git-merge Yuval Kogman 2009-01-28 13:26 ` Johannes Schindelin @ 2009-01-28 14:35 ` Sverre Rabbelier 2009-01-28 21:12 ` Junio C Hamano 2 siblings, 0 replies; 9+ messages in thread From: Sverre Rabbelier @ 2009-01-28 14:35 UTC (permalink / raw) To: Yuval Kogman; +Cc: git On Wed, Jan 28, 2009 at 13:53, Yuval Kogman <nothingmuch@woobling.org> wrote: > This patch adds an --ff-only flag to git-merge. When specified git-merge > will exit with an error whenver a merge will not be a simple fast > forward, similar to the default behavior of git push. I like! This calls for a new alias 'git config alias.integrate "merge --no-ff"', thanks! *hopes this hits next soon* -- Cheers, Sverre Rabbelier ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-28 12:53 [PATCH] Add --ff-only flag to git-merge Yuval Kogman 2009-01-28 13:26 ` Johannes Schindelin 2009-01-28 14:35 ` Sverre Rabbelier @ 2009-01-28 21:12 ` Junio C Hamano 2009-01-29 20:57 ` Yuval Kogman 2 siblings, 1 reply; 9+ messages in thread From: Junio C Hamano @ 2009-01-28 21:12 UTC (permalink / raw) To: Yuval Kogman; +Cc: git Yuval Kogman <nothingmuch@woobling.org> writes: > This patch adds an --ff-only flag to git-merge. When specified git-merge > will exit with an error whenver a merge will not be a simple fast > forward, similar to the default behavior of git push. > --- Lacks a sign-off. > @@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = { > "perform a commit if the merge succeeds (default)"), > OPT_BOOLEAN(0, "ff", &allow_fast_forward, > "allow fast forward (default)"), > + OPT_BOOLEAN(0, "ff-only", &only_fast_forward, > + "allow only fast forward"), > OPT_CALLBACK('s', "strategy", &use_strategies, "strategy", > "merge strategy to use", option_parse_strategy), > OPT_CALLBACK('m', "message", &merge_msg, "message", After parse_options() returns, there are a few existing tests to reject nonsensical combination of options. I think there are some combinations you would want to reject (for example, "--no-ff --ff-only" is an obvious such nonsensical combination, but there may be others, such as giving a strategy explicitly). > @@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) > finish(o->sha1, msg.buf); > drop_save(); > return 0; > + } else if ( only_fast_forward ) { > + printf("Merge is non fast forward, aborting.\n"); > + return 1; > } else if (!remoteheads->next && common->next) > ; This is wrong for at least three reasons: * Style of "if (expression) {", somebody else already pointed out. * Only this case exits with 1, while others die() that exits with 128. * The placement of this misses the case where a merge of two unrelated histories is attempted. You would need to also have a check at "No common ancestors found. We need a real merge." part. The octopus codepath could also end up with a fast forward or up-to-date. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-28 21:12 ` Junio C Hamano @ 2009-01-29 20:57 ` Yuval Kogman 2009-01-29 22:29 ` Junio C Hamano 0 siblings, 1 reply; 9+ messages in thread From: Yuval Kogman @ 2009-01-29 20:57 UTC (permalink / raw) To: Junio C Hamano; +Cc: git Hi, I started incorperating your feedback but before I send a new patch I have several questions about the trickier bits: 2009/1/28 Junio C Hamano <gitster@pobox.com>: > * The placement of this misses the case where a merge of two unrelated > histories is attempted. You would need to also have a check at "No > common ancestors found. We need a real merge." part. Won't that fall through? The if (!common) is above, and this is eventually an else if for it (see line 978) > The octopus > codepath could also end up with a fast forward or up-to-date. So this case is obviously more convoluted... If an octopus merge is chosen should it just pass --ff-only to git-merge-octopus? Or maybe it should always pass --ff-only and the various different strategies would just die unconditionally? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] Add --ff-only flag to git-merge 2009-01-29 20:57 ` Yuval Kogman @ 2009-01-29 22:29 ` Junio C Hamano 2009-01-30 4:32 ` [PATCH] Add --ff-only flag to git-merge (take 2) Yuval Kogman 0 siblings, 1 reply; 9+ messages in thread From: Junio C Hamano @ 2009-01-29 22:29 UTC (permalink / raw) To: Yuval Kogman; +Cc: git Yuval Kogman <nothingmuch@woobling.org> writes: > I started incorperating your feedback but before I send a new patch I > have several questions about the trickier bits: > > 2009/1/28 Junio C Hamano <gitster@pobox.com>: > >> * The placement of this misses the case where a merge of two unrelated >> histories is attempted. You would need to also have a check at "No >> common ancestors found. We need a real merge." part. > > Won't that fall through? The if (!common) is above, and this is > eventually an else if for it (see line 978) When "if (!common)" is true, the empty statement ";" is executed, and all its "else if" conditional arms will be skipped. Is that what you want to happen? >> The octopus >> codepath could also end up with a fast forward or up-to-date. > > So this case is obviously more convoluted... If an octopus merge is > chosen should it just pass --ff-only to git-merge-octopus? Or maybe it > should always pass --ff-only and the various different strategies > would just die unconditionally? I was referring to this part: } else { /* * An octopus. If we can reach all the remote we are up * to date. */ int up_to_date = 1; ... if (up_to_date) { finish_up_to_date("Already up-to-date. Yeeah!"); return 0; } } You do not want to fail this case, where you tried to merge others that have already been merged, when --ff-only is given, do you? After all, all that you are interested in is "do not create a new merge commit". If you scroll down a bit from there, you will see: /* We are going to make a new commit. */ git_committer_info(IDENT_ERROR_ON_NO_NAME); /* * At this point, we need a real merge. No matter what strategy * we use, it would operate on the index, possibly affecting the This is where "if (!common) ;" will fall through to. If your goal is to prevent the user from creating a new merge commit, the logical place to do so would be immediately before that comment, independent from all the if..elseif..fi conditional arms that come before it, I think. You also need to disable allow_trivial when ff-only is given, but I think that goes without saying. If you do not want to allow creating a new merge commit, you do not want even a trivial merge to happen. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH] Add --ff-only flag to git-merge (take 2) 2009-01-29 22:29 ` Junio C Hamano @ 2009-01-30 4:32 ` Yuval Kogman 2009-01-30 4:32 ` [PATCH] Add --ff-only flag to git-merge Yuval Kogman 0 siblings, 1 reply; 9+ messages in thread From: Yuval Kogman @ 2009-01-30 4:32 UTC (permalink / raw) To: git Hi, This attempt fixes the various issues raised, except for the case of octopus ending in 1 or more fast forwards. I'm not sure what the best way to fix this is. I see three obvious options, none of which seem optimal: 1. git-merge-octopus will take a --ff-only flag as well, adding a branch for that 2. ff-only could be a merge strategy, and octopus is forbidden in --ff-only, while this new strategy will behave just like octopus when the merge can be fast forward only. 3. the logic from git-merge-octopus could be duplicated into builtin-merge, to handle only the fast forward case. Please advise. Regards, Yuval ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH] Add --ff-only flag to git-merge 2009-01-30 4:32 ` [PATCH] Add --ff-only flag to git-merge (take 2) Yuval Kogman @ 2009-01-30 4:32 ` Yuval Kogman 0 siblings, 0 replies; 9+ messages in thread From: Yuval Kogman @ 2009-01-30 4:32 UTC (permalink / raw) To: git; +Cc: Yuval Kogman When specified git-merge will exit with an error unless the merge is resolved as a fast-forward. This is similar to the default behavior of git push. --- Documentation/merge-options.txt | 4 +++ builtin-merge.c | 18 +++++++++++++++ git-pull.sh | 4 ++- t/t7600-merge.sh | 45 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletions(-) diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 637b53f..ac742f8 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -59,6 +59,10 @@ a fast-forward, only update the branch pointer. This is the default behavior of git-merge. +--ff-only:: + Refuse to merge unless the merge is resolved as a + fast-forward. + -s <strategy>:: --strategy=<strategy>:: Use the given merge strategy; can be supplied more than diff --git a/builtin-merge.c b/builtin-merge.c index e4555b0..dae53fe 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -44,6 +44,7 @@ static const char * const builtin_merge_usage[] = { static int show_diffstat = 1, option_log, squash; static int option_commit = 1, allow_fast_forward = 1; static int allow_trivial = 1, have_message; +static int only_fast_forward; static struct strbuf merge_msg; static struct commit_list *remoteheads; static unsigned char head[20], stash[20]; @@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = { "perform a commit if the merge succeeds (default)"), OPT_BOOLEAN(0, "ff", &allow_fast_forward, "allow fast forward (default)"), + OPT_BOOLEAN(0, "ff-only", &only_fast_forward, + "allow only fast forward"), OPT_CALLBACK('s', "strategy", &use_strategies, "strategy", "merge strategy to use", option_parse_strategy), OPT_CALLBACK('m', "message", &merge_msg, "message", @@ -858,6 +861,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) option_commit = 0; } + if (only_fast_forward && !allow_fast_forward) + die("You cannot combine --ff-only with --no-ff."); + if (!argc) usage_with_options(builtin_merge_usage, builtin_merge_options); @@ -959,6 +965,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) allow_trivial = 0; } + if (only_fast_forward && !allow_fast_forward) + die("You cannot combine --ff-only with the selected" + " merge strategies."); + + if (!remoteheads->next) common = get_merge_bases(lookup_commit(head), remoteheads->item, 1); @@ -1023,6 +1034,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * We are not doing octopus, not fast forward, and have * only one common. */ + + if (only_fast_forward) + die("Merge is non fast forward, aborting."); + refresh_cache(REFRESH_QUIET); if (allow_trivial) { /* See if it is really trivial. */ @@ -1063,6 +1078,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix) } } + if (only_fast_forward) + die("Merge is non fast forward, aborting."); + /* We are going to make a new commit. */ git_committer_info(IDENT_ERROR_ON_NO_NAME); diff --git a/git-pull.sh b/git-pull.sh index 2c7f432..242d36f 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -45,6 +45,8 @@ do no_ff=--ff ;; --no-ff) no_ff=--no-ff ;; + --ff-only) + ff-only=--ff-only ;; -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ --strateg=*|--strategy=*|\ -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) @@ -185,5 +187,5 @@ merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit test true = "$rebase" && exec git-rebase $strategy_args --onto $merge_head \ ${oldremoteref:-$merge_head} -exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \ +exec git-merge $no_stat $no_commit $squash $no_ff $ff_only $log_arg $strategy_args \ "$merge_name" HEAD $merge_head $verbosity diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index e5b210b..6c2febc 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -234,6 +234,8 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' ' test_must_fail git merge -s index c1 ' +test_debug 'gitk --all' + test_expect_success 'merge c0 with c1' ' git reset --hard c0 && git merge c1 && @@ -243,6 +245,15 @@ test_expect_success 'merge c0 with c1' ' test_debug 'gitk --all' +test_expect_success 'merge c0 with c1 (fast forward only)' ' + git reset --hard c0 && + git merge --ff-only c1 && + verify_merge file result.1 && + verify_head "$c1" +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c2' ' git reset --hard c1 && test_tick && @@ -253,6 +264,14 @@ test_expect_success 'merge c1 with c2' ' test_debug 'gitk --all' +test_expect_success 'merge c1 with c2' ' + git reset --hard c1 && + test_tick && + test_must_fail git merge --ff-only c2 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c2 and c3' ' git reset --hard c1 && test_tick && @@ -263,6 +282,14 @@ test_expect_success 'merge c1 with c2 and c3' ' test_debug 'gitk --all' +test_expect_success 'merge c1 with c2 and c3 (fast forward only' ' + git reset --hard c1 && + test_tick && + test_must_fail git merge --ff-only c2 c3 +' + +test_debug 'gitk --all' + test_expect_success 'merge c0 with c1 (no-commit)' ' git reset --hard c0 && git merge --no-commit c1 && @@ -470,6 +497,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' test_debug 'gitk --all' +test_expect_success 'merge fast forward only' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + test_must_fail git merge --ff-only c0 c2 c0 c1 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c0, c2, c0, and c1' ' git reset --hard c1 && git config branch.master.mergeoptions "" && @@ -481,6 +517,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' ' test_debug 'gitk --all' +test_expect_success 'merge fast forward only' ' + git reset --hard c1 && + git config branch.master.mergeoptions "" && + test_tick && + test_must_fail git merge --ff-only c1 c2 +' + +test_debug 'gitk --all' + test_expect_success 'merge c1 with c1 and c2' ' git reset --hard c1 && git config branch.master.mergeoptions "" && -- 1.6.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-01-30 4:34 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-01-28 12:53 [PATCH] Add --ff-only flag to git-merge Yuval Kogman 2009-01-28 13:26 ` Johannes Schindelin 2009-01-28 13:29 ` Yuval Kogman 2009-01-28 14:35 ` Sverre Rabbelier 2009-01-28 21:12 ` Junio C Hamano 2009-01-29 20:57 ` Yuval Kogman 2009-01-29 22:29 ` Junio C Hamano 2009-01-30 4:32 ` [PATCH] Add --ff-only flag to git-merge (take 2) Yuval Kogman 2009-01-30 4:32 ` [PATCH] Add --ff-only flag to git-merge Yuval Kogman
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).