aboutsummaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/meson.build2
-rwxr-xr-xt/t3450-history.sh17
-rwxr-xr-xt/t3451-history-reword.sh391
-rwxr-xr-xt/t3650-replay-basics.sh9
4 files changed, 419 insertions, 0 deletions
diff --git a/t/meson.build b/t/meson.build
index 19e8306298..a04a7a86cf 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -387,6 +387,8 @@ integration_tests = [
't3436-rebase-more-options.sh',
't3437-rebase-fixup-options.sh',
't3438-rebase-broken-files.sh',
+ 't3450-history.sh',
+ 't3451-history-reword.sh',
't3500-cherry.sh',
't3501-revert-cherry-pick.sh',
't3502-cherry-pick-merge.sh',
diff --git a/t/t3450-history.sh b/t/t3450-history.sh
new file mode 100755
index 0000000000..f513463b92
--- /dev/null
+++ b/t/t3450-history.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description='tests for git-history command'
+
+. ./test-lib.sh
+
+test_expect_success 'does nothing without any arguments' '
+ test_must_fail git history 2>err &&
+ test_grep "need a subcommand" err
+'
+
+test_expect_success 'raises an error with unknown argument' '
+ test_must_fail git history garbage 2>err &&
+ test_grep "unknown subcommand: .garbage." err
+'
+
+test_done
diff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh
new file mode 100755
index 0000000000..3594421b68
--- /dev/null
+++ b/t/t3451-history-reword.sh
@@ -0,0 +1,391 @@
+#!/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 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 '--ref-action=print 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 --ref-action=print 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 '--ref-action=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 history reword --ref-action=head theirs 2>err &&
+ test_grep "rewritten commit must be an ancestor of HEAD" err &&
+
+ reword_with_message --ref-action=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
diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh
index 307101eeb9..c862aa39f3 100755
--- a/t/t3650-replay-basics.sh
+++ b/t/t3650-replay-basics.sh
@@ -249,6 +249,15 @@ test_expect_success 'using replay on bare repo to rebase multiple divergent bran
done
'
+test_expect_success 'using replay to update detached HEAD' '
+ current_head=$(git branch --show-current) &&
+ test_when_finished git switch "$current_head" &&
+ git switch --detach &&
+ test_commit something &&
+ git replay --ref-action=print --onto HEAD~2 --ref-action=print HEAD~..HEAD >updates &&
+ test_grep "update HEAD " updates
+'
+
test_expect_success 'merge.directoryRenames=false' '
# create a test case that stress-tests the rename caching
git switch -c rename-onto &&