"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
James Cook <falsifian@falsifian.org>
Subject:
(test&doc only) RFC: allow editing merge commit messages
To:
gameoftrees@openbsd.org
Date:
Sun, 08 Nov 2026 02:19:47 +0000

Download raw body.

Thread
I am very particular about my merge commit messages.* The below
patch adds documentation and regress for a -e option to got merge,
which would open an editor for the merge commit message.

(It also adds the existing -M flag to got's usage message.

Two questions:

1. Is this feature wanted?

2. How about having it as the default? That would be my own preference;
   I never want the message got auto-generates.

If there's interest, I hope to find some time over the next few
weeks to implement it. (Or I'd be more than happy if someone else
did. I'm a little oversubscribed, but very interested in having this.)

(Since I haven't yet implemented merge -e, I can't actually see
whether the regress in the below patch works as intended.)

-- 
James

*Rant: Merges don't make history complicated, if you follow this
simple rule: a commit message should describe the difference against
the first parent. So, "Add sprocket support", not "Merge dev/sprocket".
This way, for example, tog's default view (or git log --first-parent)
gives you a clean history. The fact that a merge was involved is
less important that what actually changed. See e.g.
https://www.davidchudzicki.com/posts/first-parent/

 
diff eff4b972377331c3faf693c81c0b90e0aa8fe60664709c4e3697d427e51a0232 e3d7552d3abcad67ea816ed6127218e558466471e34c30e38c98bfe252de3c7c
commit - eff4b972377331c3faf693c81c0b90e0aa8fe60664709c4e3697d427e51a0232
commit + e3d7552d3abcad67ea816ed6127218e558466471e34c30e38c98bfe252de3c7c
blob - c8599390ed653733a727b64abd9d1e3ee0ae347250c22e844ac538ac774c9209
blob + 3a9604a5c78c0b88b26806ba1c57f1dfdbc234fad1f21e7e9784831ca87d2144
--- got/got.1
+++ got/got.1
@@ -3574,6 +3574,8 @@ option.
 Continue an interrupted merge operation.
 If this option is used, no other command-line arguments are allowed except
 .Fl C .
+.It Fl e
+Open an editor where the log message can be edited before creating the merge commit.
 .It Fl M
 Create a merge commit even if the branches have not diverged.
 .It Fl n
blob - e5e5b850baef35c829bdf371109a690e6aaa1e504279eba09e25cee504cb58e7
blob + 14805d6d45865ce8f85615a2f01eca069e87e71868a854b363f12b348fc83ccb
--- got/got.c
+++ got/got.c
@@ -13791,7 +13791,7 @@ __dead static void
 usage_merge(int status)
 {
 	FILE *fp = (status == 0) ? stdout : stderr;
-	fprintf(fp, "usage: %s merge [-aCcn] [branch]\n", getprogname());
+	fprintf(fp, "usage: %s merge [-aCceMn] [branch]\n", getprogname());
 	exit(status);
 }
 
@@ -13822,7 +13822,7 @@ cmd_merge(int argc, char *argv[])
 		err(1, "pledge");
 #endif
 
-	while ((ch = getopt(argc, argv, "aCcMn")) != -1) {
+	while ((ch = getopt(argc, argv, "aCceMn")) != -1) {
 		switch (ch) {
 		case 'a':
 			abort_merge = 1;
@@ -13833,6 +13833,9 @@ cmd_merge(int argc, char *argv[])
 		case 'c':
 			continue_merge = 1;
 			break;
+		case 'e':
+			/* XXX */
+			break;
 		case 'M':
 			prefer_fast_forward = 0;
 			break;
blob - e8b1cfa9c442fe171483597aef029d231a2d4477c338047edcd9e87606457438
blob + 3e7e18b0c5f115cac86db13624cc6ef05e6eebf1ddec34124cc7082c2a957a9d
--- regress/cmdline/merge.sh
+++ regress/cmdline/merge.sh
@@ -1240,6 +1240,177 @@ EOF
 	test_done "$testroot" "$ret"
 }
 
+test_merge_edit_message() {
+	local testroot=`test_init merge_edit_message`
+
+	# create divergent commits on master and newbranch
+	git -C $testroot/repo checkout -q -b newbranch
+	echo "modified beta on branch" > $testroot/repo/beta
+	git_commit $testroot/repo -m "committing to beta on newbranch"
+	local branch_commit0=`git_show_branch_head $testroot/repo newbranch`
+	git -C $testroot/repo checkout -q master
+	echo "modified alpha on master" > $testroot/repo/alpha
+	git_commit $testroot/repo -m "committing to alpha on master"
+
+	got checkout -b master $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got checkout failed unexpectedly" >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	cat > $testroot/editor.sh <<EOF
+#!/bin/sh
+echo new commit message > $1
+EOF
+
+	(cd $testroot/wt && env VISUAL="$testroot/editor.sh" \
+		got merge -e newbranch > /dev/null)
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "'got merge' failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	(cd $testroot/wt && got log -l1 | grep '^ ') > $testroot/log
+	cat > $testroot/log.expected <<EOF
+ 
+ new commit message
+ 
+EOF
+ 
+	cmp -s $testroot/log.expected $testroot/log
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/log.expected $testroot/log
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	test_done "$testroot" 0
+}
+
+test_merge_editor_continue() {
+	local testroot=`test_init merge_edit_message`
+
+	# create divergent commits on master and newbranch
+	git -C $testroot/repo checkout -q -b newbranch
+	echo "modified beta on branch" > $testroot/repo/beta
+	git_commit $testroot/repo -m "committing to beta on newbranch"
+	local branch_commit0=`git_show_branch_head $testroot/repo newbranch`
+	git -C $testroot/repo checkout -q master
+	echo "modified alpha on master" > $testroot/repo/alpha
+	git_commit $testroot/repo -m "committing to alpha on master"
+
+	got checkout -b master $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got checkout failed unexpectedly" >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	cat > $testroot/editor.sh <<EOF
+#!/bin/sh
+echo new commit message > $1
+EOF
+
+	(cd $testroot/wt && got merge -n newbranch > /dev/null)
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "'got merge' failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	(cd $testroot/wt && env VISUAL="$testroot/editor.sh" got merge -ce > /dev/null)
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "'got merge' failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	(cd $testroot/wt && got log -l1 | grep '^ ') > $testroot/log
+	cat > $testroot/log.expected <<EOF
+ 
+ new commit message
+ 
+EOF
+ 
+	cmp -s $testroot/log.expected $testroot/log
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/log.expected $testroot/log
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	test_done "$testroot" 0
+}
+
+test_merge_editor_fail() {
+	local testroot=`test_init merge_edit_message`
+
+	# create divergent commits on master and newbranch
+	git -C $testroot/repo checkout -q -b newbranch
+	echo "modified beta on branch" > $testroot/repo/beta
+	git_commit $testroot/repo -m "committing to beta on newbranch"
+	local branch_commit0=`git_show_branch_head $testroot/repo newbranch`
+	git -C $testroot/repo checkout -q master
+	echo "modified alpha on master" > $testroot/repo/alpha
+	git_commit $testroot/repo -m "committing to alpha on master"
+
+	got checkout -b master $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got checkout failed unexpectedly" >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	cat > $testroot/editor.sh <<EOF
+#!/bin/sh
+echo this should be ignored > $1
+exit 1
+EOF
+
+	(cd $testroot/wt && env VISUAL="$testroot/editor.sh" \
+		got merge -e newbranch > /dev/null)
+	ret=$?
+	if [ $ret -eq 0 ]; then
+		echo "'got merge' succeeded unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	(cd $testroot/wt && got merge -c)
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "'got merge' failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	(cd $testroot/wt && got log -l1 | grep '^ ') > $testroot/log
+	cat > $testroot/log.expected <<EOF
+ 
+ merge newbranch into master
+EOF
+ 
+	cmp -s $testroot/log.expected $testroot/log
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/log.expected $testroot/log
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	test_done "$testroot" 0
+}
+
 test_merge_path_prefix() {
 	local testroot=`test_init merge_path_prefix`
 	local commit0=`git_show_head $testroot/repo`
@@ -2702,6 +2873,9 @@ run_test test_merge_continue
 run_test test_merge_continue_new_commit
 run_test test_merge_abort
 run_test test_merge_in_progress
+run_test test_merge_edit_message
+run_test test_merge_editor_fail
+run_test test_merge_editor_continue
 run_test test_merge_path_prefix
 run_test test_merge_missing_file
 run_test test_merge_no_op