summaryrefslogtreecommitdiff
path: root/t/t3432-rebase-fast-forward.sh
AgeCommit message (Collapse)AuthorFilesLines
2020-02-16rebase: rename the two primary rebase backendsLibravatar Elijah Newren1-2/+2
Two related changes, with separate rationale for each: Rename the 'interactive' backend to 'merge' because: * 'interactive' as a name caused confusion; this backend has been used for many kinds of non-interactive rebases, and will probably be used in the future for more non-interactive rebases than interactive ones given that we are making it the default. * 'interactive' is not the underlying strategy; merging is. * the directory where state is stored is not called .git/rebase-interactive but .git/rebase-merge. Rename the 'am' backend to 'apply' because: * Few users are familiar with git-am as a reference point. * Related to the above, the name 'am' makes sentences in the documentation harder for users to read and comprehend (they may read it as the verb from "I am"); avoiding this difficult places a large burden on anyone writing documentation about this backend to be very careful with quoting and sentence structure and often forces annoying redundancy to try to avoid such problems. * Users stumble over pronunciation ("am" as in "I am a person not a backend" or "am" as in "the first and thirteenth letters in the alphabet in order are "A-M"); this may drive confusion when one user tries to explain to another what they are doing. * While "am" is the tool driving this backend, the tool driving git-am is git-apply, and since we are driving towards lower-level tools for the naming of the merge backend we may as well do so here too. * The directory where state is stored has never been called .git/rebase-am, it was always called .git/rebase-apply. For all the reasons listed above: * Modify the documentation to refer to the backends with the new names * Provide a brief note in the documentation connecting the new names to the old names in case users run across the old names anywhere (e.g. in old release notes or older versions of the documentation) * Change the (new) --am command line flag to --apply * Rename some enums, variables, and functions to reinforce the new backend names for us as well. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-16rebase tests: mark tests specific to the am-backend with --amLibravatar Elijah Newren1-2/+2
We have many rebase tests in the testsuite, and often the same test is repeated multiple times just testing different backends. For those tests that were specifically trying to test the am backend, add the --am flag. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-16rebase: allow more types of rebases to fast-forwardLibravatar Elijah Newren1-0/+2
In the past, we dis-allowed rebases using the interactive backend from performing a fast-forward to short-circuit the rebase operation. This made sense for explicitly interactive rebases and some implicitly interactive rebases, but certainly became overly stringent when the merge backend was re-implemented via the interactive backend. Just as the am-based rebase has always had to disable the fast-forward based on a variety of conditions or flags (e.g. --signoff, --whitespace, etc.), we need to do the same but now with a few more options. However, continuing to use REBASE_FORCE for tracking this is problematic because the interactive backend used it for a different purpose. (When REBASE_FORCE wasn't set, the interactive backend would not fast-forward the whole series but would fast-forward individual "pick" commits at the beginning of the todo list, and then a squash or something would cause it to start generating new commits.) So, introduce a new allow_preemptive_ff flag contained within cmd_rebase() and use it to track whether we are going to allow a pre-emptive fast-forward that short-circuits the whole rebase. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-16t3432: make these tests work with either am or merge backendsLibravatar Elijah Newren1-26/+22
t3432 had several stress tests for can_fast_forward(), whose intent was to ensure we were using the optimization of just fast forwarding when possible. However, these tests verified that fast forwards had happened based on the output that rebase printed to the terminal. We can instead test more directly that we actually fast-forwarded by checking the reflog, which also has the side effect of making the tests applicable for the merge/interactive backend. This change does lose the distinction between "noop" and "noop-force", but as stated in commit c9efc216830f ("t3432: test for --no-ff's interaction with fast-forward", 2019-08-27) which introduced that distinction: "These tests aren't supposed to endorse the status quo, just test for what we're currently doing.". This change does not actually run these tests with the merge/interactive backend; instead this is just a preparatory commit. A subsequent commit which fixes can_fast_forward() to work with that backend will then also change t3432 to add tests of that backend as well. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-21t: teach test_cmp_rev to accept ! for not-equalsLibravatar Denton Liu1-1/+1
In the case where we are using test_cmp_rev() to report not-equals, we write `! test_cmp_rev`. However, since test_cmp_rev() contains r1=$(git rev-parse --verify "$1") && r2=$(git rev-parse --verify "$2") && `! test_cmp_rev` will succeed if any of the rev-parses fail. This behavior is not desired. We want the rev-parses to _always_ be successful. Rewrite test_cmp_rev() to optionally accept "!" as the first argument to do a not-equals comparison. Rewrite `! test_cmp_rev` to `test_cmp_rev !` in all tests to take advantage of this new functionality. Also, rewrite the rev-parse logic to end with a `|| return 1` instead of &&-chaining into the rev-comparison logic. This makes it obvious to future readers that we explicitly intend on returning early if either of the rev-parses fail. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-27rebase: teach rebase --keep-baseLibravatar Denton Liu1-0/+11
A common scenario is if a user is working on a topic branch and they wish to make some changes to intermediate commits or autosquash, they would run something such as git rebase -i --onto master... master in order to preserve the merge base. This is useful when contributing a patch series to the Git mailing list, one often starts on top of the current 'master'. While developing the patches, 'master' is also developed further and it is sometimes not the best idea to keep rebasing on top of 'master', but to keep the base commit as-is. In addition to this, a user wishing to test individual commits in a topic branch without changing anything may run git rebase -x ./test.sh master... master Since rebasing onto the merge base of the branch and the upstream is such a common case, introduce the --keep-base option as a shortcut. This allows us to rewrite the above as git rebase -i --keep-base master and git rebase -x ./test.sh --keep-base master respectively. Add tests to ensure --keep-base works correctly in the normal case and fails when there are multiple merge bases, both in regular and interactive mode. Also, test to make sure conflicting options cause rebase to fail. While we're adding test cases, add a missing set_fake_editor call to 'rebase -i --onto master...side'. While we're documenting the --keep-base option, change an instance of "merge-base" to "merge base", which is the consistent spelling. Helped-by: Eric Sunshine <sunshine@sunshineco.com> Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-27rebase: fast-forward --fork-point in more casesLibravatar Denton Liu1-10/+10
Before, when we rebased with a --fork-point invocation where the fork-point wasn't empty, we would be setting options.restrict_revision. The fast-forward logic would automatically declare that the rebase was not fast-forwardable if it was set. However, this was painting with a very broad brush. Refine the logic so that we can fast-forward in the case where the restricted revision is equal to the merge base, since we stop rebasing at the merge base anyway. Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-27rebase: fast-forward --onto in more casesLibravatar Denton Liu1-2/+2
Before, when we had the following graph, A---B---C (master) \ D (side) running 'git rebase --onto master... master side' would result in D being always rebased, no matter what. However, the desired behavior is that rebase should notice that this is fast-forwardable and do that instead. Add detection to `can_fast_forward` so that this case can be detected and a fast-forward will be performed. First of all, rewrite the function to use gotos which simplifies the logic. Next, since the options.upstream && !oidcmp(&options.upstream->object.oid, &options.onto->object.oid) conditions were removed in `cmd_rebase`, we reintroduce a substitute in `can_fast_forward`. In particular, checking the merge bases of `upstream` and `head` fixes a failing case in t3416. The abbreviated graph for t3416 is as follows: F---G topic / A---B---C---D---E master and the failing command was git rebase --onto master...topic F topic Before, Git would see that there was one merge base (C), and the merge and onto were the same so it would incorrectly return 1, indicating that we could fast-forward. This would cause the rebased graph to be 'ABCFG' when we were expecting 'ABCG'. With the additional logic, we detect that upstream and head's merge base is F. Since onto isn't F, it means we're not rebasing the full set of commits from master..topic. Since we're excluding some commits, a fast-forward cannot be performed and so we correctly return 0. Add '-f' to test cases that failed as a result of this change because they were not expecting a fast-forward so that a rebase is forced. Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-27t3432: test for --no-ff's interaction with fast-forwardLibravatar Ævar Arnfjörð Bjarmason1-29/+54
Add more stress tests for the can_fast_forward() case in rebase.c. These tests are getting rather verbose, but now we can see under --ff and --no-ff whether we skip work, or whether we're forced to run the rebase. These tests aren't supposed to endorse the status quo, just test for what we're currently doing. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-26t3432: distinguish "noop-same" v.s. "work-same" in "same head" testsLibravatar Ævar Arnfjörð Bjarmason1-31/+48
Change "same head" introduced in the preceding commit to check whether the rebase.c code lands in the can_fast_forward() case in, and thus prints out an "is up to date" and aborts early. In some of these cases we make it past that and to "rewinding head", then do a rebase, only to find out there's nothing to change so HEAD stays at the same OID. These tests presumed these two cases were the same thing. In terms of where HEAD ends up they are, but we're not only interested in rebase semantics, but also whether or not we're needlessly doing work when we could avoid it entirely. I'm adding "same" and "diff" here because I'll follow-up and add --no-ff tests, where some of those will be "diff"-erent, so add the "diff" code already. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-26t3432: test rebase fast-forward behaviorLibravatar Denton Liu1-0/+72
When rebase is run on a branch that can be fast-forwarded, this should automatically be done. Create test to ensure this behavior happens. There are some cases that currently don't pass. The first case is where a feature and master have diverged, running "git rebase master... master" causes a full rebase to happen even though a fast-forward should happen. The second case is when we are doing "git rebase --fork-point" and a fork-point commit is found. Once again, a full rebase happens even though a fast-forward should happen. Mark these cases as failure so we can fix it later. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>