mirror of
https://github.com/git-for-windows/git.git
synced 2026-05-03 02:27:35 -05:00
With the preceding commit we have changed "--ref-action=" to only control which refs are supposed to be updated, not what happens with them. As a consequence, the option is now somewhat misnamed, as we don't control the action itself anymore. Rename it to "--update-refs=" to better align it with its new use. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
400 lines
7.9 KiB
Bash
Executable File
400 lines
7.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='tests for git-history reword subcommand'
|
|
|
|
. ./test-lib.sh
|
|
. "$TEST_DIRECTORY/lib-log-graph.sh"
|
|
|
|
reword_with_message () {
|
|
cat >message &&
|
|
write_script fake-editor.sh <<-\EOF &&
|
|
cp message "$1"
|
|
EOF
|
|
test_set_editor "$(pwd)"/fake-editor.sh &&
|
|
git history reword "$@" &&
|
|
rm fake-editor.sh message
|
|
}
|
|
|
|
expect_graph () {
|
|
cat >expect &&
|
|
lib_test_cmp_graph --graph --format=%s "$@"
|
|
}
|
|
|
|
expect_log () {
|
|
git log --format="%s" "$@" >actual &&
|
|
cat >expect &&
|
|
test_cmp expect actual
|
|
}
|
|
|
|
test_expect_success 'can reword tip of a branch' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
test_commit third &&
|
|
|
|
git symbolic-ref HEAD >expect &&
|
|
reword_with_message HEAD <<-EOF &&
|
|
third reworded
|
|
EOF
|
|
git symbolic-ref HEAD >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
expect_log <<-\EOF &&
|
|
third reworded
|
|
second
|
|
first
|
|
EOF
|
|
|
|
git reflog >reflog &&
|
|
test_grep "reword: updating HEAD" reflog
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword commit in the middle' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
test_commit third &&
|
|
|
|
git symbolic-ref HEAD >expect &&
|
|
reword_with_message HEAD~ <<-EOF &&
|
|
second reworded
|
|
EOF
|
|
git symbolic-ref HEAD >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
expect_log <<-\EOF
|
|
third
|
|
second reworded
|
|
first
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword commit in the middle even on detached head' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
test_commit third_on_main &&
|
|
git checkout --detach HEAD^ &&
|
|
test_commit third_on_head &&
|
|
|
|
reword_with_message HEAD~ <<-EOF &&
|
|
second reworded
|
|
EOF
|
|
|
|
expect_graph HEAD --branches <<-\EOF
|
|
* third_on_head
|
|
| * third_on_main
|
|
|/
|
|
* second reworded
|
|
* first
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword the detached head' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
git checkout --detach HEAD &&
|
|
test_commit third &&
|
|
|
|
reword_with_message HEAD <<-EOF &&
|
|
third reworded
|
|
EOF
|
|
|
|
expect_log <<-\EOF
|
|
third reworded
|
|
second
|
|
first
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword root commit' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
test_commit third &&
|
|
reword_with_message HEAD~2 <<-EOF &&
|
|
first reworded
|
|
EOF
|
|
|
|
expect_log <<-\EOF
|
|
third
|
|
second
|
|
first reworded
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword in a bare repo' '
|
|
test_when_finished "rm -rf repo repo.git" &&
|
|
git init repo &&
|
|
test_commit -C repo first &&
|
|
git clone --bare repo repo.git &&
|
|
(
|
|
cd repo.git &&
|
|
reword_with_message HEAD <<-EOF &&
|
|
reworded
|
|
EOF
|
|
|
|
expect_log <<-\EOF
|
|
reworded
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword a commit on a different branch' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit base &&
|
|
git branch theirs &&
|
|
test_commit ours &&
|
|
git switch theirs &&
|
|
test_commit theirs &&
|
|
|
|
git rev-parse ours >ours-before &&
|
|
reword_with_message theirs <<-EOF &&
|
|
Reworded theirs
|
|
EOF
|
|
git rev-parse ours >ours-after &&
|
|
test_cmp ours-before ours-after &&
|
|
|
|
expect_graph --branches <<-\EOF
|
|
* Reworded theirs
|
|
| * ours
|
|
|/
|
|
* base
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'can reword a merge commit' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit base &&
|
|
git branch branch &&
|
|
test_commit ours &&
|
|
git switch branch &&
|
|
test_commit theirs &&
|
|
git switch - &&
|
|
git merge theirs &&
|
|
|
|
# It is not possible to replay merge commits embedded in the
|
|
# history (yet).
|
|
test_must_fail git -c core.editor=false history reword HEAD~ 2>err &&
|
|
test_grep "replaying merge commits is not supported yet" err &&
|
|
|
|
# But it is possible to reword a merge commit directly.
|
|
reword_with_message HEAD <<-EOF &&
|
|
Reworded merge commit
|
|
EOF
|
|
expect_graph <<-\EOF
|
|
* Reworded merge commit
|
|
|\
|
|
| * theirs
|
|
* | ours
|
|
|/
|
|
* base
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success '--dry-run prints ref updates without modifying repo' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo --initial-branch=main &&
|
|
(
|
|
cd repo &&
|
|
test_commit base &&
|
|
git branch branch &&
|
|
test_commit ours &&
|
|
git switch branch &&
|
|
test_commit theirs &&
|
|
|
|
git refs list >refs-expect &&
|
|
reword_with_message --dry-run --update-refs=head base >updates <<-\EOF &&
|
|
reworded commit
|
|
EOF
|
|
git refs list >refs-actual &&
|
|
test_cmp refs-expect refs-actual &&
|
|
test_grep "update refs/heads/branch" updates &&
|
|
test_grep ! "update refs/heads/main" updates &&
|
|
|
|
reword_with_message --dry-run base >updates <<-\EOF &&
|
|
reworded commit
|
|
EOF
|
|
git refs list >refs-actual &&
|
|
test_cmp refs-expect refs-actual &&
|
|
|
|
test_grep "update refs/heads/branch" updates &&
|
|
test_grep "update refs/heads/main" updates &&
|
|
git update-ref --stdin <updates &&
|
|
expect_log --branches <<-\EOF
|
|
theirs
|
|
ours
|
|
reworded commit
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success '--update-refs=head updates only HEAD' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo --initial-branch=main &&
|
|
(
|
|
cd repo &&
|
|
test_commit base &&
|
|
git branch branch &&
|
|
test_commit theirs &&
|
|
git switch branch &&
|
|
test_commit ours &&
|
|
|
|
# When told to update HEAD, only, the command will refuse to
|
|
# rewrite commits that are not an ancestor of HEAD.
|
|
test_must_fail git -c core.editor=false history reword --update-refs=head theirs 2>err &&
|
|
test_grep "rewritten commit must be an ancestor of HEAD" err &&
|
|
|
|
reword_with_message --update-refs=head base >updates <<-\EOF &&
|
|
reworded base
|
|
EOF
|
|
expect_log HEAD <<-\EOF &&
|
|
ours
|
|
reworded base
|
|
EOF
|
|
expect_log main <<-\EOF
|
|
theirs
|
|
base
|
|
EOF
|
|
)
|
|
'
|
|
|
|
test_expect_success 'editor shows proper status' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
|
|
write_script fake-editor.sh <<-\EOF &&
|
|
cp "$1" . &&
|
|
printf "\namend a comment\n" >>"$1"
|
|
EOF
|
|
test_set_editor "$(pwd)"/fake-editor.sh &&
|
|
git history reword HEAD &&
|
|
|
|
cat >expect <<-EOF &&
|
|
first
|
|
|
|
# Please enter the commit message for the reworded changes. Lines starting
|
|
# with ${SQ}#${SQ} will be ignored, and an empty message aborts the commit.
|
|
# Changes to be committed:
|
|
# new file: first.t
|
|
#
|
|
EOF
|
|
test_cmp expect COMMIT_EDITMSG &&
|
|
|
|
test_commit_message HEAD <<-\EOF
|
|
first
|
|
|
|
amend a comment
|
|
EOF
|
|
)
|
|
'
|
|
|
|
# For now, git-history(1) does not yet execute any hooks. This is subject to
|
|
# change in the future, and if it does this test here is expected to start
|
|
# failing. In other words, this test is not an endorsement of the current
|
|
# status quo.
|
|
test_expect_success 'hooks are not executed for rewritten commits' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
test_commit second &&
|
|
test_commit third &&
|
|
|
|
ORIG_PATH="$(pwd)" &&
|
|
export ORIG_PATH &&
|
|
for hook in prepare-commit-msg pre-commit post-commit post-rewrite commit-msg
|
|
do
|
|
write_script .git/hooks/$hook <<-\EOF || exit 1
|
|
touch "$ORIG_PATH/hooks.log
|
|
EOF
|
|
done &&
|
|
|
|
reword_with_message HEAD~ <<-EOF &&
|
|
second reworded
|
|
EOF
|
|
|
|
cat >expect <<-EOF &&
|
|
third
|
|
second reworded
|
|
first
|
|
EOF
|
|
git log --format=%s >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
test_path_is_missing hooks.log
|
|
)
|
|
'
|
|
|
|
test_expect_success 'aborts with empty commit message' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
test_commit first &&
|
|
|
|
! reword_with_message HEAD 2>err </dev/null &&
|
|
test_grep "Aborting commit due to empty commit message." err
|
|
)
|
|
'
|
|
|
|
test_expect_success 'retains changes in the worktree and index' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
(
|
|
cd repo &&
|
|
touch a b &&
|
|
git add . &&
|
|
git commit -m "initial commit" &&
|
|
echo foo >a &&
|
|
echo bar >b &&
|
|
git add b &&
|
|
reword_with_message HEAD <<-EOF &&
|
|
message
|
|
EOF
|
|
cat >expect <<-\EOF &&
|
|
M a
|
|
M b
|
|
?? actual
|
|
?? expect
|
|
EOF
|
|
git status --porcelain >actual &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_done
|