[PATCH] Let format-patch and rebase ignore trivial merges.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As git rebase and git format-patch linearize commits,
having the same change in different branches causes in the
best case duplicate patches in the produced series and in the
worst case conflicts. If there are trivial merges involved
(i.e. merges that do not change the tree), then this patch
will cause git to only look at one branch, thereby avoiding
duplicates and reducing the chance of conflicts.

There are two new options --prune-tree and --no-prune-tree
added.

--prune-tree makes rev-list without paths equivalent to
"git rev-list $options -- ." (or .. or ../.. and so on,
if you are in some subdirectory).
This is the new default for format-patch and rebase

--no-prune-tree deactivates --prune-tree.

Signed-off-by: Bernhard R. Link <brlink@xxxxxxxxxx>
---
 Documentation/rev-list-options.txt |   11 +++++++++++
 builtin-log.c                      |    1 +
 git-rebase--interactive.sh         |    1 +
 git-rebase.sh                      |    2 +-
 revision.c                         |   11 ++++++++++-
 revision.h                         |    1 +
 6 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 1f57aed..6c5e90c 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -328,6 +328,17 @@ The following options select the commits to be shown:
 
 	Commits modifying the given <paths> are selected.
 
+--prune-tree::
+
+	No paths is equivalent to the whole tree as path.
+	That means merges with the same tree follow only one parent.
+	(Default for format-patch and rebase).
+
+--no-prune-tree::
+
+	No paths means not doing history simplification based on paths.
+	(Default for everything but format-patch and rebase).
+
 --simplify-by-decoration::
 
 	Commits that are referred by some branch or tag are selected.
diff --git a/builtin-log.c b/builtin-log.c
index 1766349..efc2f40 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -960,6 +960,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	rev.diff = 1;
 	rev.combine_merges = 0;
 	rev.ignore_merges = 1;
+	rev.prune_tree = 1;
 	DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
 
 	rev.subject_prefix = fmt_patch_subject_prefix;
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0bd3bf7..ea23d9b 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -703,6 +703,7 @@ first and then run 'git rebase --continue' again."
 		fi
 		git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
 			--abbrev=7 --reverse --left-right --topo-order \
+			--prune-tree \
 			$REVISIONS | \
 			sed -n "s/^>//p" | while read shortsha1 rest
 		do
diff --git a/git-rebase.sh b/git-rebase.sh
index b121f45..2186619 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -539,7 +539,7 @@ echo "$head_name" > "$dotest/head-name"
 echo "$GIT_QUIET" > "$dotest/quiet"
 
 msgnum=0
-for cmt in `git rev-list --reverse --no-merges "$revisions"`
+for cmt in `git rev-list --reverse --no-merges --prune-tree "$revisions"`
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$dotest/cmt.$msgnum"
diff --git a/revision.c b/revision.c
index a8a3c3a..3350af6 100644
--- a/revision.c
+++ b/revision.c
@@ -1112,6 +1112,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->dense = 1;
 	} else if (!strcmp(arg, "--sparse")) {
 		revs->dense = 0;
+	} else if (!strcmp(arg, "--prune-tree")) {
+		revs->prune_tree = 1;
+	} else if (!strcmp(arg, "--no-prune-tree")) {
+		revs->prune_tree = 0;
 	} else if (!strcmp(arg, "--show-all")) {
 		revs->show_all = 1;
 	} else if (!strcmp(arg, "--remove-empty")) {
@@ -1408,8 +1412,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 		}
 	}
 
-	if (prune_data)
+	if (prune_data) {
 		revs->prune_data = get_pathspec(revs->prefix, prune_data);
+	} else if (revs->prune_tree) {
+		/* limit whole tree (limits trivial merges to one side) */
+		static const char *whole_tree[2] = { "", NULL };
+		revs->prune_data = whole_tree;
+	}
 
 	if (revs->def == NULL)
 		revs->def = def;
diff --git a/revision.h b/revision.h
index d368003..d007aaa 100644
--- a/revision.h
+++ b/revision.h
@@ -38,6 +38,7 @@ struct rev_info {
 	/* Traversal flags */
 	unsigned int	dense:1,
 			prune:1,
+			prune_tree:1,
 			no_merges:1,
 			merges_only:1,
 			no_walk:1,
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]