Re: Cherry-pick dangles and forgets helpful advice in next

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

 



Phil Hord <hordp@xxxxxxxxx> writes:

> This sequence fails to report an error as of this commit:
>
> commit b27cfb0d8d4cbb6d079c70ffeadac9c0dcfff250
> Author: Neil Horman <nhorman@xxxxxxxxxxxxx>
> Date:   Fri Apr 20 10:36:15 2012 -0400
>
>     git-cherry-pick: Add keep-redundant-commits option

Yes, because it deliberately breaks sequencer.c::do_pick_commit() in this
particular case:

	if (!empty_commit && !opts->keep_redundant_commits && index_unchanged)
		/*
		 * The head tree and the index match
		 * meaning the commit is empty.  Since it wasn't created
		 * empty (based on the previous test), we can conclude
		 * the commit has been made redundant.  Since we don't
		 * want to keep redundant commits, we can just return
		 * here, skipping this commit
		 */
		return 0;

which is not quite right.  We do not want to keep redundant commits, so
this needs to error out as before.

I will queue the following in the meantime.

-- >8 --
Subject: [PATCH] Revert nh/empty-rebase topic

The topic breaks "git cherry-pick $commit" that results in no change
in the tree by not erroring out, which is a grave regression.

Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx>
---
 Documentation/git-cherry-pick.txt |  19 -------
 Documentation/git-rebase.txt      |   4 --
 builtin/revert.c                  |   8 ---
 git-rebase--am.sh                 |  19 ++-----
 git-rebase--interactive.sh        |  35 ++-----------
 git-rebase.sh                     |   5 --
 sequencer.c                       | 103 ++++----------------------------------
 sequencer.h                       |   2 -
 t/t3505-cherry-pick-empty.sh      |  25 +--------
 9 files changed, 19 insertions(+), 201 deletions(-)

diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 9f3dae6..06a0bfd 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -103,25 +103,6 @@ effect to your index in a row.
 	cherry-pick'ed commit, then a fast forward to this commit will
 	be performed.
 
---allow-empty::
-	By default, cherry-picking an empty commit will fail,
-	indicating that an explicit invocation of `git commit
-	--allow-empty` is required. This option overrides that
-	behavior, allowing empty commits to be preserved automatically
-	in a cherry-pick. Note that when "--ff" is in effect, empty
-	commits that meet the "fast-forward" requirement will be kept
-	even without this option.  Note also, that use of this option only
-	keeps commits that were initially empty (i.e. the commit recorded the
-	same tree as its parent).  Commits which are made empty due to a
-	previous commit are dropped.  To force the inclusion of those commits
-	use `--keep-redundant-commits`.
-
---keep-redundant-commits::
-	If a commit being cherry picked duplicates a commit already in the
-	current history, it will become empty.  By default these
-	redundant commits are ignored.  This option overrides that behavior and
-	creates an empty commit object.  Implies `--allow-empty`.
-
 --strategy=<strategy>::
 	Use the given merge strategy.  Should only be used once.
 	See the MERGE STRATEGIES section in linkgit:git-merge[1]
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 147fa1a..b0e13e5 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -238,10 +238,6 @@ leave out at most one of A and B, in which case it defaults to HEAD.
 	will be reset to where it was when the rebase operation was
 	started.
 
---keep-empty::
-	Keep the commits that do not change anything from its
-	parents in the result.
-
 --skip::
 	Restart the rebasing process by skipping the current patch.
 
diff --git a/builtin/revert.c b/builtin/revert.c
index 82d1bf8..5462e67 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -115,16 +115,12 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 		OPT_END(),
 		OPT_END(),
 		OPT_END(),
-		OPT_END(),
-		OPT_END(),
 	};
 
 	if (opts->action == REPLAY_PICK) {
 		struct option cp_extra[] = {
 			OPT_BOOLEAN('x', NULL, &opts->record_origin, "append commit name"),
 			OPT_BOOLEAN(0, "ff", &opts->allow_ff, "allow fast-forward"),
-			OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, "preserve initially empty commits"),
-			OPT_BOOLEAN(0, "keep-redundant-commits", &opts->keep_redundant_commits, "keep redundant, empty commits"),
 			OPT_END(),
 		};
 		if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
@@ -142,10 +138,6 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 				"--abort", rollback,
 				NULL);
 
-	/* implies allow_empty */
-	if (opts->keep_redundant_commits)
-		opts->allow_empty = 1;
-
 	/* Set the subcommand */
 	if (remove_state)
 		opts->subcommand = REPLAY_REMOVE_STATE;
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 04d8941..c815a24 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -20,20 +20,11 @@ esac
 
 test -n "$rebase_root" && root_flag=--root
 
-if test -n "$keep_empty"
-then
-	# we have to do this the hard way.  git format-patch completely squashes
-	# empty commits and even if it didn't the format doesn't really lend
-	# itself well to recording empty patches.  fortunately, cherry-pick
-	# makes this easy
-	git cherry-pick --allow-empty "$revisions"
-else
-	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-		--src-prefix=a/ --dst-prefix=b/ \
-		--no-renames $root_flag "$revisions" |
-	git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
-fi && move_to_original_branch
-
+git format-patch -k --stdout --full-index --ignore-if-in-upstream \
+	--src-prefix=a/ --dst-prefix=b/ \
+	--no-renames $root_flag "$revisions" |
+git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
+move_to_original_branch
 ret=$?
 test 0 != $ret -a -d "$state_dir" && write_basic_state
 exit $ret
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0c19b7c..2e13258 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -167,14 +167,6 @@ has_action () {
 	sane_grep '^[^#]' "$1" >/dev/null
 }
 
-is_empty_commit() {
-	tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null ||
-		die "$1: not a commit that can be picked")
-	ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null ||
-		ptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904)
-	test "$tree" = "$ptree"
-}
-
 # Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
 # GIT_AUTHOR_DATE exported from the current environment.
 do_with_author () {
@@ -199,19 +191,12 @@ git_sequence_editor () {
 
 pick_one () {
 	ff=--ff
-
 	case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac
 	case "$force_rebase" in '') ;; ?*) ff= ;; esac
 	output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
-
-	if is_empty_commit "$sha1"
-	then
-		empty_args="--allow-empty"
-	fi
-
 	test -d "$rewritten" &&
 		pick_one_preserving_merges "$@" && return
-	output git cherry-pick $empty_args $ff "$@"
+	output git cherry-pick $ff "$@"
 }
 
 pick_one_preserving_merges () {
@@ -795,17 +780,9 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \
 	sed -n "s/^>//p" |
 while read -r shortsha1 rest
 do
-
-	if test -z "$keep_empty" && is_empty_commit $shortsha1
-	then
-		comment_out="# "
-	else
-		comment_out=
-	fi
-
 	if test t != "$preserve_merges"
 	then
-		printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
+		printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
 	else
 		sha1=$(git rev-parse $shortsha1)
 		if test -z "$rebase_root"
@@ -824,7 +801,7 @@ do
 		if test f = "$preserve"
 		then
 			touch "$rewritten"/$sha1
-			printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
+			printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
 		fi
 	fi
 done
@@ -876,12 +853,6 @@ cat >> "$todo" << EOF
 #
 EOF
 
-if test -z "$keep_empty"
-then
-	echo "# Note that empty commits are commented out" >>"$todo"
-fi
-
-
 has_action "$todo" ||
 	die_abort "Nothing to do"
 
diff --git a/git-rebase.sh b/git-rebase.sh
index 24a2840..69c1374 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -43,7 +43,6 @@ s,strategy=!       use the given merge strategy
 no-ff!             cherry-pick all commits, even if unchanged
 m,merge!           use merging strategies to rebase
 i,interactive!     let the user edit the list of commits to rebase
-k,keep-empty	   preserve empty commits during rebase
 f,force-rebase!    force rebase even if branch is up to date
 X,strategy-option=! pass the argument through to the merge strategy
 stat!              display a diffstat of what changed upstream
@@ -98,7 +97,6 @@ state_dir=
 action=
 preserve_merges=
 autosquash=
-keep_empty=
 test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 
 read_basic_state () {
@@ -222,9 +220,6 @@ do
 	-i)
 		interactive_rebase=explicit
 		;;
-	-k)
-		keep_empty=yes
-		;;
 	-p)
 		preserve_merges=t
 		test -z "$interactive_rebase" && interactive_rebase=implied
diff --git a/sequencer.c b/sequencer.c
index 3c384b9..81d8ace 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -13,7 +13,6 @@
 #include "rerere.h"
 #include "merge-recursive.h"
 #include "refs.h"
-#include "argv-array.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -252,38 +251,6 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
 	return !clean;
 }
 
-static int is_index_unchanged(void)
-{
-	unsigned char head_sha1[20];
-	struct commit *head_commit;
-
-	if (!resolve_ref_unsafe("HEAD", head_sha1, 1, NULL))
-		return error(_("Could not resolve HEAD commit\n"));
-
-	head_commit = lookup_commit(head_sha1);
-
-	/*
-	 * If head_commit is NULL, check_commit, called from
-	 * lookup_commit, would have indicated that head_commit is not
-	 * a commit object already.  parse_commit() will return failure
-	 * without further complaints in such a case.  Otherwise, if
-	 * the commit is invalid, parse_commit() will complain.  So
-	 * there is nothing for us to say here.  Just return failure.
-	 */
-	if (parse_commit(head_commit))
-		return -1;
-
-	if (!active_cache_tree)
-		active_cache_tree = cache_tree();
-
-	if (!cache_tree_fully_valid(active_cache_tree))
-		if (cache_tree_update(active_cache_tree, active_cache,
-				  active_nr, 0))
-			return error(_("Unable to update cache tree\n"));
-
-	return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.sha1);
-}
-
 /*
  * If we are cherry-pick, and if the merge did not result in
  * hand-editing, we will hit this commit and inherit the original
@@ -293,46 +260,21 @@ static int is_index_unchanged(void)
  */
 static int run_git_commit(const char *defmsg, struct replay_opts *opts)
 {
-	struct argv_array array;
-	int rc;
-
-	argv_array_init(&array);
-	argv_array_push(&array, "commit");
-	argv_array_push(&array, "-n");
+	/* 6 is max possible length of our args array including NULL */
+	const char *args[6];
+	int i = 0;
 
+	args[i++] = "commit";
+	args[i++] = "-n";
 	if (opts->signoff)
-		argv_array_push(&array, "-s");
+		args[i++] = "-s";
 	if (!opts->edit) {
-		argv_array_push(&array, "-F");
-		argv_array_push(&array, defmsg);
+		args[i++] = "-F";
+		args[i++] = defmsg;
 	}
+	args[i] = NULL;
 
-	if (opts->allow_empty)
-		argv_array_push(&array, "--allow-empty");
-
-	rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
-	argv_array_clear(&array);
-	return rc;
-}
-
-static int is_original_commit_empty(struct commit *commit)
-{
-	const unsigned char *ptree_sha1;
-
-	if (parse_commit(commit))
-		return error(_("Could not parse commit %s\n"),
-			     sha1_to_hex(commit->object.sha1));
-	if (commit->parents) {
-		struct commit *parent = commit->parents->item;
-		if (parse_commit(parent))
-			return error(_("Could not parse parent commit %s\n"),
-				sha1_to_hex(parent->object.sha1));
-		ptree_sha1 = parent->tree->object.sha1;
-	} else {
-		ptree_sha1 = EMPTY_TREE_SHA1_BIN; /* commit is root */
-	}
-
-	return !hashcmp(ptree_sha1, commit->tree->object.sha1);
+	return run_command_v_opt(args, RUN_GIT_CMD);
 }
 
 static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
@@ -344,8 +286,6 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 	char *defmsg = NULL;
 	struct strbuf msgbuf = STRBUF_INIT;
 	int res;
-	int empty_commit;
-	int index_unchanged;
 
 	if (opts->no_commit) {
 		/*
@@ -471,10 +411,6 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		free_commit_list(remotes);
 	}
 
-	empty_commit = is_original_commit_empty(commit);
-	if (empty_commit < 0)
-		return empty_commit;
-
 	/*
 	 * If the merge was clean or if it failed due to conflict, we write
 	 * CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
@@ -495,25 +431,6 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 		print_advice(res == 1, opts);
 		rerere(opts->allow_rerere_auto);
 	} else {
-		index_unchanged = is_index_unchanged();
-		/*
-		 * If index_unchanged is less than 0, that indicates we either
-		 * couldn't parse HEAD or the index, so error out here.
-		 */
-		if (index_unchanged < 0)
-			return index_unchanged;
-
-		if (!empty_commit && !opts->keep_redundant_commits && index_unchanged)
-			/*
-			 * The head tree and the index match
-			 * meaning the commit is empty.  Since it wasn't created
-			 * empty (based on the previous test), we can conclude
-			 * the commit has been made redundant.  Since we don't
-			 * want to keep redundant commits, we can just return
-			 * here, skipping this commit
-			 */
-			return 0;
-
 		if (!opts->no_commit)
 			res = run_git_commit(defmsg, opts);
 	}
diff --git a/sequencer.h b/sequencer.h
index aa5f17c..bb4b138 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -29,8 +29,6 @@ struct replay_opts {
 	int signoff;
 	int allow_ff;
 	int allow_rerere_auto;
-	int allow_empty;
-	int keep_redundant_commits;
 
 	int mainline;
 
diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
index 92f00cd..c10b28c 100755
--- a/t/t3505-cherry-pick-empty.sh
+++ b/t/t3505-cherry-pick-empty.sh
@@ -18,12 +18,7 @@ test_expect_success setup '
 	echo third >> file1 &&
 	git add file1 &&
 	test_tick &&
-	git commit --allow-empty-message -m "" &&
-
-	git checkout master &&
-	git checkout -b empty-branch2 &&
-	test_tick &&
-	git commit --allow-empty -m "empty"
+	git commit --allow-empty-message -m ""
 
 '
 
@@ -53,22 +48,4 @@ test_expect_success 'index lockfile was removed' '
 
 '
 
-test_expect_success 'cherry pick an empty non-ff commit without --allow-empty' '
-	git checkout master &&
-	echo fourth >>file2 &&
-	git add file2 &&
-	git commit -m "fourth" &&
-	test_must_fail git cherry-pick empty-branch2
-'
-
-test_expect_success 'cherry pick an empty non-ff commit with --allow-empty' '
-	git checkout master &&
-	git cherry-pick --allow-empty empty-branch2
-'
-
-test_expect_success 'cherry pick with --keep-redundant-commits' '
-	git checkout master &&
-	git cherry-pick --keep-redundant-commits HEAD^
-'
-
 test_done
-- 
1.7.10.2.627.g7c93d77


--
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]