mirror of
https://github.com/git/git
synced 2024-11-05 01:58:18 +00:00
bf6ab087d1
If "git rebase" fails to start after stashing the user's uncommitted changes then it forgets to restore the stashed changes and remove the state directory. To make matters worse, running "git rebase --abort" to apply the stashed changes and cleanup the state directory fails because the state directory only contains the "autostash" file and is missing the "head-name" and "onto" files required by read_basic_state(). Fix this by applying the autostash and removing the state directory if the pre-rebase hook or initial checkout fail. This matches what finish_rebase() does at the end of a successful rebase. If the user modifies any files after the autostash is created it is possible there will be conflicts when the autostash is applied. In that case apply_autostash() saves the stash in a new entry under refs/stash and so it is safe to remove the state directory containing the autostash file. New tests are added to check the autostash is applied and the state directory is removed if the rebase fails to start. Checks are also added to some existing tests in order to ensure there is no state directory left behind when a rebase fails to start and no autostash has been created. Reported-by: Brian Lyles <brianmlyles@gmail.com> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
142 lines
3.5 KiB
Bash
Executable file
142 lines
3.5 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='git rebase with its hook(s)'
|
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success setup '
|
|
echo hello >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m initial &&
|
|
echo goodbye >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m second &&
|
|
git checkout -b side HEAD^ &&
|
|
echo world >git &&
|
|
git add git &&
|
|
test_tick &&
|
|
git commit -m side &&
|
|
git checkout main &&
|
|
git log --pretty=oneline --abbrev-commit --graph --all &&
|
|
git branch test side
|
|
'
|
|
|
|
test_expect_success 'rebase' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git rebase main &&
|
|
test "z$(cat git)" = zworld
|
|
'
|
|
|
|
test_expect_success 'rebase -i' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
EDITOR=true git rebase -i main &&
|
|
test "z$(cat git)" = zworld
|
|
'
|
|
|
|
test_expect_success 'setup pre-rebase hook' '
|
|
test_hook --setup pre-rebase <<-\EOF
|
|
echo "$1,$2" >.git/PRE-REBASE-INPUT
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (1)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git rebase main &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,
|
|
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (2)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git rebase main test &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,test
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (3)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git checkout main &&
|
|
git rebase main test &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,test
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (4)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
EDITOR=true git rebase -i main &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,
|
|
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (5)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
EDITOR=true git rebase -i main test &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,test
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook gets correct input (6)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git checkout main &&
|
|
EDITOR=true git rebase -i main test &&
|
|
test "z$(cat git)" = zworld &&
|
|
test "z$(cat .git/PRE-REBASE-INPUT)" = zmain,test
|
|
'
|
|
|
|
test_expect_success 'setup pre-rebase hook that fails' '
|
|
test_hook --setup --clobber pre-rebase <<-\EOF
|
|
false
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook stops rebase (1)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
test_must_fail git rebase main &&
|
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
|
|
test 0 = $(git rev-list HEAD...side | wc -l) &&
|
|
test_must_fail git rebase --quit 2>err &&
|
|
test_grep "no rebase in progress" err
|
|
'
|
|
|
|
test_expect_success 'pre-rebase hook stops rebase (2)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
test_must_fail env EDITOR=: git rebase -i main &&
|
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
|
|
test 0 = $(git rev-list HEAD...side | wc -l)
|
|
'
|
|
|
|
test_expect_success 'rebase --no-verify overrides pre-rebase (1)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
git rebase --no-verify main &&
|
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
|
|
test "z$(cat git)" = zworld
|
|
'
|
|
|
|
test_expect_success 'rebase --no-verify overrides pre-rebase (2)' '
|
|
git checkout test &&
|
|
git reset --hard side &&
|
|
EDITOR=true git rebase --no-verify -i main &&
|
|
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
|
|
test "z$(cat git)" = zworld
|
|
'
|
|
|
|
test_done
|