[PATCH 1/2] builtin/rebase.c: Emit warning when rebasing without a forkpoint
- From
Wesley Schwengle <wesleys@opperschaap.net>
- Date
- Aug 19, 2023, 20:34 UTC
- Message-ID
- <20230819203528.562156-2-wesleys@opperschaap.net>
- In-Reply-To
- <20230819203528.562156-1-wesleys@opperschaap.net>
When commit d1e894c6d7 (Document `rebase.forkpoint` in rebase man page, 2021-09-16) was submitted there was a discussion on if the forkpoint behaviour of `git rebase' was sane. In my experience this wasn't sane. Git rebase doesn't work if you don't have an upstream branch configured (or something that says `merge = refs/heads/master' in the git config). The behaviour of `git rebase' was that if you supply an upstream on the command line that it behaves as if `--no-forkpoint' was supplied and if you don't supply an upstream, it behaves as if `--forkpoint' was supplied. This can result in a loss of commits if you don't know that and if you don't know about `git reflog' or have other copies of your changes. This can be seen with the following reproduction path:
mkdir reproduction
cd reproduction
git init .
echo "commit a" > file.txt
git add file.txt
git commit -m "First commit" file.txt
echo "commit b" >> file.txt
git commit -m "Second commit" file.txt git switch -c foo
echo "commit c" >> file.txt"
git commit -m "Third commit" file.txt
git branch --set-upstream-to=master git status
On branch foo
Your branch is ahead of 'master' by 1 commit. git switch master
git merge foo
git reset --hard HEAD^
git switch foo
Switched to branch 'foo'
Your branch is ahead of 'master' by 1 commit. git log --format='%C(yellow)%h%Creset %Cgreen%s%Creset'
5f427e3 Third commit
03ad791 Second commit
411e6d4 First commit git rebase
git status
On branch foo
Your branch is up to date with 'master'. git log --format='%C(yellow)%h%Creset %Cgreen%s%Creset'
03ad791 Second commit
411e6d4 First commitThis patch adds a warning where it will indicate that `rebase.forkpoint' must be set in the git configuration and/or that you can supply a `--forkpoint' or `--no-forkpoint' command line option to your `git rebase' invocation.
Signed-off-by: Wesley Schwengle <wesleys@opperschaap.net> --- builtin/rebase.c | 15 ++++++++++- t/t3431-rebase-fork-point.sh | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/builtin/rebase.c b/builtin/rebase.c index 50cb85751f..41dd9b6256 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -1604,8 +1604,21 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) NULL); if (!options.upstream_name) error_on_missing_default_upstream(); - if (options.fork_point < 0) + if (options.fork_point < 0) { + warning(_( + "Rebasing without specifying a forkpoint is discouraged. You can squelch\n" + "this message by running one of the following commands something before your\n" + "next rebase:\n" + "\n" + " git config rebase.forkpoint = false # This will become the new default\n" + " git config rebase.forkpoint = true # This is the old default\n" + "\n" + "You can replace \"git config\" with \"git config --global\" to set a default\n" + "preference for all repositories. You can also pass --no-fork-point, --fork-point\n" + "on the command line to override the configured default per invocation.\n" + )); options.fork_point = 1; + } } else { options.upstream_name = argv[0]; argc--; diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh index 4bfc779bb8..a583ca6228 100755 --- a/t/t3431-rebase-fork-point.sh +++ b/t/t3431-rebase-fork-point.sh @@ -113,4 +113,54 @@ test_expect_success 'rebase.forkPoint set to true and --root given' ' git rebase --root ' +# The use of the diff -qw is because there is some kind of whitespace character +# magic going on which probably has to do with the tabs. It only occurs when we +# check STDERR +test_expect_success 'rebase without forkpoint' ' + git init rebase-forkpoint && + cd rebase-forkpoint && + git status >/tmp/foo && + echo "commit a" > file.txt && + git add file.txt && + git commit -m "First commit" file.txt && + echo "commit b" >> file.txt && + git commit -m "Second commit" file.txt && + git switch -c foo && + echo "commit c" >> file.txt && + git commit -m "Third commit" file.txt && + git branch --set-upstream-to=main && + git switch main && + git merge foo && + git reset --hard HEAD^ && + git switch foo && + commit=$(git log -n1 --format="%h") && + git rebase >out 2>err && + test_must_be_empty out && + cat <<-\OEF > expect && + warning: Rebasing without specifying a forkpoint is discouraged. You can squelch + this message by running one of the following commands something before your + next rebase: + + git config rebase.forkpoint = false # This will become the new default + git config rebase.forkpoint = true # This is the old default + + You can replace "git config" with "git config --global" to set a default + preference for all repositories. You can also pass --no-fork-point, --fork-point + on the command line to override the configured default per invocation. + + Successfully rebased and updated refs/heads/foo. + OEF + diff -qw expect err && + git reset --hard $commit && + git rebase --fork-point >out 2>err && + test_must_be_empty out && + echo "Successfully rebased and updated refs/heads/foo." > expect && + diff -qw expect err && + git reset --hard $commit && + git rebase --no-fork-point >out 2>err && + test_must_be_empty err && + echo "Current branch foo is up to date." > expect && + test_cmp out expect +' + test_done
-- 2.42.0.rc2.7.gf9972720e9.dirty