git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC] git commit --branch

From
Martin Waitz <tali@admingilde.org>
Date
May 29, 2006, 20:28 UTC
Message-ID
<20060529202851.GE14325@admingilde.org>
Allow to commit to another branch and creating a merge in the current branch.

Sometimes it is neccessary to have some local modifications in the tree in order to test it and work with it. With this patch you can have one working tree which combines several topic branches in order to develop and test your changes. When your changes are ready, you can commit them to the appropriate topic branch.

With the --branch option, the commit will automatically be rebased to that branch. The original tree will then be commited to your working branch as a merge.

---

Perhaps something like this can even be integrated into the extended branch configuration which is currently under discussion. It may make sense to have one branch which always contains a merge of a selected set of other branches and having a default branch for new commits.

 Documentation/git-commit.txt        |    6 +++
 git-commit.sh                       |   62 ++++++++++++++++++++++++++++++++++-
 t/t3800-commit-onto-other-branch.sh |   32 ++++++++++++++++++
 3 files changed, 99 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 38df59c..8111ba4 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -49,6 +49,12 @@ OPTIONS
 	Override the author name used in the commit.  Use
 	`A U Thor <author@example.com>` format.
 
+--branch <branch>::
+	Actually commit the changes to another branch.
+	Afterwards it will be merged into the current branch.
+	This is useful if you work on a branch with local modifications
+	but want to keep one clean branch without those.
+
 -m <msg>::
 	Use the given <msg> as the commit message.
 
diff --git a/git-commit.sh b/git-commit.sh
index 1983d45..9ed0050 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -3,7 +3,7 @@ #
 # Copyright (c) 2005 Linus Torvalds
 # Copyright (c) 2006 Junio C Hamano
 
-USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [[-i | -o] <path>...]'
+USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [--branch <branch>] [[-i | -o] <path>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 
@@ -245,6 +245,12 @@ do
       force_author="$1"
       shift
       ;;
+  -b|--b|--br|--bra|--bran|--branc|--branch)
+      case "$#" in 1) usage ;; esac
+      shift
+      onto_branch="$1"
+      shift
+      ;;
   -e|--e|--ed|--edi|--edit)
       no_edit=
       shift
@@ -405,6 +411,7 @@ t,,[1-9]*)
 	die "No paths with -i does not make sense." ;;
 esac
 
+
 ################################################################
 # Prepare index to have a tree to be committed
 
@@ -623,6 +630,32 @@ else
 	current=
 fi
 
+if test -n "$onto_branch"
+then
+	onto_branch_commit=$(git-rev-parse --verify "$onto_branch") ||
+		die "Branch $onto_branch does not exist."
+	test $(git merge-base "$onto_branch" HEAD) = $onto_branch_commit ||
+		die "Branch "$onto_branch" already contains unmerged commits."
+	case "$PARENTS" in
+	-p*-p*)	die "Cannot commit a merge to another branch." ;;
+	esac
+	if test $(git-rev-parse --verify HEAD) = $onto_branch_commit
+	then
+		# no merge neccessary, branches identically
+		forward_onto_branch="$onto_branch"
+		onto_branch=""
+	fi
+	if test "$amend" = t
+	then
+		# test that the tip of HEAD really came from the tip of
+		# $onto_branch and that we can amend both of them
+		test $(git merge-base "$onto_branch" HEAD^) != $onto_branch_commit &&
+		test $(git merge-base "$onto_branch"^ HEAD^) = $(git rev-parse --verify "$onto_branch"^) ||
+			die "commits on $onto_branch and HEAD differ, cannot amend."
+		onto_branch_commit=$(git rev-parse --verify "$onto_branch"^)
+	fi
+fi
+
 if test -z "$no_edit"
 then
 	{
@@ -689,8 +722,35 @@ then
 		tree=$(GIT_INDEX_FILE="$TMP_INDEX" git-write-tree) &&
 		rm -f "$TMP_INDEX"
 	fi &&
+	if test -n "$onto_branch"
+	then
+		# create temporary index
+		ONTO_INDEX="$GIT_DIR/onto-index"
+		cp "$USE_INDEX" "$ONTO_INDEX" &&
+		GIT_INDEX_FILE="$ONTO_INDEX" \
+		git-read-tree -i -m "$onto_branch_commit"
+		# merge new changes into the branch
+		GIT_INDEX_FILE="$ONTO_INDEX" \
+		git-read-tree -i --aggressive -m \
+			HEAD "$onto_branch_commit" "$tree" &&
+		GIT_INDEX_FILE="$ONTO_INDEX" \
+		git-merge-index git-merge-one-file -a || {
+			echo >&2 "Cannot rebase your commit to $onto_branch."
+			echo >&2 "Please merge and commit manually."
+			false
+		} &&
+		tree2=$(GIT_INDEX_FILE="$ONTO_INDEX" git-write-tree) &&
+		commit2=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree2 -p $onto_branch_commit) &&
+		git update-ref "$onto_branch" $commit2 &&
+		rm -f "$ONTO_INDEX" &&
+		PARENTS="$PARENTS -p $commit2"
+	fi &&
 	commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
 	git-update-ref HEAD $commit $current &&
+	if test -n "$forward_onto_branch"
+	then
+		git-update-ref "$forward_onto_branch" $commit $current
+	fi &&
 	rm -f -- "$GIT_DIR/MERGE_HEAD" &&
 	if test -f "$NEXT_INDEX"
 	then
diff --git a/t/t3800-commit-onto-other-branch.sh b/t/t3800-commit-onto-other-branch.sh
new file mode 100755
index 0000000..f4f6410
--- /dev/null
+++ b/t/t3800-commit-onto-other-branch.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Martin Waitz
+#
+
+test_description='Test a commit to another branch'
+
+. ./test-lib.sh
+
+echo AAA > A
+echo BBB > B
+
+test_expect_success 'Initial commit' \
+'git add A B &&
+ git commit -m "Initial commit" &&
+ git branch topic'
+
+test_expect_success 'Modify HEAD' \
+'echo A2 > A &&
+ git commit -m "modify A" A'
+
+test_expect_success 'Commit to branch' \
+'echo B2 > B &&
+ git commit -m "modify B" --branch topic B'
+
+# now test that HEAD and topic only differs in A
+test_expect_success 'Verify trees' \
+'echo ":100644 100644 43d5a8e... 3ce238a... M	A" > expected &&
+ git diff-tree --abbrev topic HEAD > current &&
+ diff expected current'
+
+test_done
-- 
1.3.3.ged90


-- 
Martin Waitz
Next: Shawn Pearce
Message 1 of 15 in “[RFC] git commit --branch”
  1. Martin WaitzMay 29, 2006
  2. Shawn PearceMay 29, 2006
  3. Martin WaitzMay 29, 2006
  4. Shawn PearceMay 29, 2006
  5. Martin WaitzMay 29, 2006
  6. Shawn PearceMay 29, 2006
  7. Johannes SchindelinMay 29, 2006
  8. Jakub NarebskiMay 29, 2006
  9. Martin WaitzMay 29, 2006
  10. Johannes SchindelinMay 29, 2006
  11. Junio C HamanoMay 30, 2006
  12. Martin WaitzMay 30, 2006
  13. Junio C HamanoMay 30, 2006
  14. Martin WaitzMay 31, 2006
  15. Jon LoeligerJun 5, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.