From 620c190492aef39de0f83e3f4df1cce4be621723 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 6 Jul 2026 12:33:55 -0700 Subject: [PATCH 1/6] New program `git-test-mergetool.sh` --- git-test-mergetool.sh | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 git-test-mergetool.sh diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh new file mode 100755 index 0000000..1afc496 --- /dev/null +++ b/git-test-mergetool.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +## Run this script, or cut-and-paste its commands into a shell, to test +## your Git mergetool. + +mkdir -p /tmp/"${USER}" +cd /tmp/"${USER}" || { + echo "cannot cd to /tmp/${USER}" + exit +} + +rm -rf repo clone1 clone2 + +mkdir repo +cd repo || exit +git init --bare +cd .. + +git clone repo clone1 +git clone repo clone2 + +cd clone1 || exit +printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9' > file.txt +echo 'Foo bar' > file2.txt +echo 'Baz quux' > file3.txt +git add file.txt file2.txt file3.txt +git commit -m "Initial contents" +git push +cd .. + +cd clone2 || exit +git pull +cd .. + +cd clone1 || exit +printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9' > file.txt +echo 'Foo bar in 1' > file2.txt +echo 'Baz quux in 1' > file3.txt +git commit -m "Changes in clone 1" file.txt file2.txt file3.txt +git push +cd .. + +cd clone2 || exit +printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9' > file.txt +echo 'Baz quux in 2' > file3.txt +git commit -m "Changes in clone 2" file.txt file3.txt +git pull +git mergetool From 1ad8228b0dd1f0fa397379ecb42b5a6b62af62d4 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 20 Jul 2026 11:53:37 -0700 Subject: [PATCH 2/6] Update git-test-mergetool.sh Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- git-test-mergetool.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh index 1afc496..1ea7c9e 100755 --- a/git-test-mergetool.sh +++ b/git-test-mergetool.sh @@ -17,20 +17,16 @@ git init --bare cd .. git clone repo clone1 -git clone repo clone2 - cd clone1 || exit printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9' > file.txt echo 'Foo bar' > file2.txt echo 'Baz quux' > file3.txt git add file.txt file2.txt file3.txt git commit -m "Initial contents" -git push +git push -u origin HEAD cd .. -cd clone2 || exit -git pull -cd .. +git clone repo clone2 cd clone1 || exit printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9' > file.txt From 257e8a01184b878f09bb8a1288fac472f6a2b8c5 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 20 Jul 2026 11:53:47 -0700 Subject: [PATCH 3/6] Use non-zero exit code --- git-test-mergetool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh index 1afc496..b83daa6 100755 --- a/git-test-mergetool.sh +++ b/git-test-mergetool.sh @@ -6,7 +6,7 @@ mkdir -p /tmp/"${USER}" cd /tmp/"${USER}" || { echo "cannot cd to /tmp/${USER}" - exit + exit 2 } rm -rf repo clone1 clone2 From 20742254ce7d12a494a4231459a8a3c6c370aa92 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 20 Jul 2026 11:54:35 -0700 Subject: [PATCH 4/6] Update git-test-mergetool.sh Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- git-test-mergetool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh index 1ea7c9e..d345c63 100755 --- a/git-test-mergetool.sh +++ b/git-test-mergetool.sh @@ -40,5 +40,5 @@ cd clone2 || exit printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9' > file.txt echo 'Baz quux in 2' > file3.txt git commit -m "Changes in clone 2" file.txt file3.txt -git pull +git pull --no-rebase --no-ff git mergetool From 95cf13ae9282828920e466d2656344773f692868 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 20 Jul 2026 11:55:21 -0700 Subject: [PATCH 5/6] Newline at end of file --- git-test-mergetool.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh index ac5a486..92d2439 100755 --- a/git-test-mergetool.sh +++ b/git-test-mergetool.sh @@ -18,7 +18,7 @@ cd .. git clone repo clone1 cd clone1 || exit -printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9' > file.txt +printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9\n' > file.txt echo 'Foo bar' > file2.txt echo 'Baz quux' > file3.txt git add file.txt file2.txt file3.txt @@ -29,7 +29,7 @@ cd .. git clone repo clone2 cd clone1 || exit -printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9' > file.txt +printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9\n' > file.txt echo 'Foo bar in 1' > file2.txt echo 'Baz quux in 1' > file3.txt git commit -m "Changes in clone 1" file.txt file2.txt file3.txt @@ -37,7 +37,7 @@ git push cd .. cd clone2 || exit -printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9' > file.txt +printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9\n' > file.txt echo 'Baz quux in 2' > file3.txt git commit -m "Changes in clone 2" file.txt file3.txt git pull --no-rebase --no-ff From cf2e8426e777f3a8fa967f6b0f43e85142378703 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 20 Jul 2026 12:05:52 -0700 Subject: [PATCH 6/6] Code review --- README.md | 6 ++++ git-test-mergetool | 66 +++++++++++++++++++++++++++++++++++++++++++ git-test-mergetool.sh | 44 ----------------------------- 3 files changed, 72 insertions(+), 44 deletions(-) create mode 100755 git-test-mergetool delete mode 100755 git-test-mergetool.sh diff --git a/README.md b/README.md index 2207dca..edf500f 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,12 @@ Tests whether a branch exists in a Git repository; prints the branch, or prints "master" if the branch does not exist. [Documentation](git-find-branch) at top of file. +### git-test-mergetool + +Creates a scratch repository containing a merge conflict, then runs +`git mergetool` on it, so that you can test your Git mergetool. +[Documentation](git-test-mergetool) at top of file. + ### resolve-adjacent-conflicts Edits files in place to resolve git conflicts that arise from edits to diff --git a/git-test-mergetool b/git-test-mergetool new file mode 100755 index 0000000..78ae5ed --- /dev/null +++ b/git-test-mergetool @@ -0,0 +1,66 @@ +#!/bin/sh + +# git-test-mergetool: test your Git mergetool on a scratch repository. +# +# Usage: git-test-mergetool +# +# Run this script, or cut-and-paste its commands into a shell. It deletes +# and recreates the directories /tmp/$USER/repo, /tmp/$USER/clone1, and +# /tmp/$USER/clone2, then creates a merge conflict in /tmp/$USER/clone2 and +# runs `git mergetool` on it. +# +# The merge conflicts in two files, file.txt and file3.txt; a third file, +# file2.txt, merges cleanly and the mergetool should not be run on it. +# +# Requirements: `merge.tool` must be set in your Git configuration, as must +# `user.name` and `user.email`. +# +# After the mergetool exits, the merge is not complete: resolve any +# remaining conflicts, then run `git commit`. The mergetool may leave +# `*.orig` files behind. + +set -e + +USER="${USER:-$(id -un)}" +SCRATCH_DIR="/tmp/${USER:?}" + +mkdir -p "${SCRATCH_DIR}" +cd "${SCRATCH_DIR}" || { + echo "cannot cd to ${SCRATCH_DIR}" >&2 + exit 2 +} + +rm -rf repo clone1 clone2 + +mkdir repo +cd repo || exit 2 +git init --bare -q --initial-branch=main +cd .. + +git clone repo clone1 +cd clone1 || exit 2 +printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9\n' > file.txt +echo 'Foo bar' > file2.txt +echo 'Baz quux' > file3.txt +git add file.txt file2.txt file3.txt +git commit -m "Initial contents" +git push -u origin HEAD +cd .. + +git clone repo clone2 + +cd clone1 || exit 2 +printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9\n' > file.txt +echo 'Foo bar in 1' > file2.txt +echo 'Baz quux in 1' > file3.txt +git commit -m "Changes in clone 1" file.txt file2.txt file3.txt +git push +cd .. + +cd clone2 || exit 2 +printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9\n' > file.txt +echo 'Baz quux in 2' > file3.txt +git commit -m "Changes in clone 2" file.txt file3.txt +# This is expected to fail, because the merge conflicts. +git pull --no-rebase --no-ff || true +git mergetool diff --git a/git-test-mergetool.sh b/git-test-mergetool.sh deleted file mode 100755 index 92d2439..0000000 --- a/git-test-mergetool.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -## Run this script, or cut-and-paste its commands into a shell, to test -## your Git mergetool. - -mkdir -p /tmp/"${USER}" -cd /tmp/"${USER}" || { - echo "cannot cd to /tmp/${USER}" - exit 2 -} - -rm -rf repo clone1 clone2 - -mkdir repo -cd repo || exit -git init --bare -cd .. - -git clone repo clone1 -cd clone1 || exit -printf 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nLine 8\nLine 9\n' > file.txt -echo 'Foo bar' > file2.txt -echo 'Baz quux' > file3.txt -git add file.txt file2.txt file3.txt -git commit -m "Initial contents" -git push -u origin HEAD -cd .. - -git clone repo clone2 - -cd clone1 || exit -printf 'Line 1\nLine 2 in 1\nLine 3\nLine 4\nLine 5\nLine 6 in 1\nLine 7 in 1\nLine 8\nLine 9\n' > file.txt -echo 'Foo bar in 1' > file2.txt -echo 'Baz quux in 1' > file3.txt -git commit -m "Changes in clone 1" file.txt file2.txt file3.txt -git push -cd .. - -cd clone2 || exit -printf 'Line 1\nLine 2\nLine 3\nLine 4 in 2\nLine 5\nLine 6\nLine 7 in 2\nLine 8 in 2\nLine 9\n' > file.txt -echo 'Baz quux in 2' > file3.txt -git commit -m "Changes in clone 2" file.txt file3.txt -git pull --no-rebase --no-ff -git mergetool