$ git rebase master
* Applying: Redo "revert" using three-way merge machinery.
First trying simple merge strategy to cherry-pick.
-Finished one cherry-pick.
* Applying: Remove git-apply-patch-script.
First trying simple merge strategy to cherry-pick.
Simple cherry-pick fails; trying Automatic cherry-pick.
Removing Documentation/git-apply-patch-script.txt
Removing git-apply-patch-script
-Finished one cherry-pick.
* Applying: Document "git cherry-pick" and "git revert"
First trying simple merge strategy to cherry-pick.
-Finished one cherry-pick.
* Applying: mailinfo and applymbox updates
First trying simple merge strategy to cherry-pick.
-Finished one cherry-pick.
* Applying: Show commits in topo order and name all commits.
First trying simple merge strategy to cherry-pick.
-Finished one cherry-pick.
* Applying: More documentation updates.
First trying simple merge strategy to cherry-pick.
-Finished one cherry-pick.
------------------------------------------------
The temporary tag 'pu-anchor' is me just being careful, in case 'git
sha1_to_hex(commit->object.sha1));
}
-static char *help_msg(void)
+static void advise(const char *advice, ...)
{
- struct strbuf helpbuf = STRBUF_INIT;
- char *msg = getenv("GIT_CHERRY_PICK_HELP");
+ va_list params;
- if (msg)
- return msg;
+ va_start(params, advice);
+ vreportf("hint: ", advice, params);
+ va_end(params);
+}
- strbuf_addstr(&helpbuf, " After resolving the conflicts,\n"
- "mark the corrected paths with 'git add <paths>' or 'git rm <paths>'\n"
- "and commit the result");
+static void print_advice(void)
+{
+ char *msg = getenv("GIT_CHERRY_PICK_HELP");
- if (action == CHERRY_PICK) {
- strbuf_addf(&helpbuf, " with: \n"
- "\n"
- " git commit -c %s\n",
- sha1_to_hex(commit->object.sha1));
+ if (msg) {
+ fprintf(stderr, "%s\n", msg);
+ return;
}
- else
- strbuf_addch(&helpbuf, '.');
- return strbuf_detach(&helpbuf, NULL);
+
+ advise("after resolving the conflicts, mark the corrected paths");
+ advise("with 'git add <paths>' or 'git rm <paths>'");
+
+ if (action == CHERRY_PICK)
+ advise("and commit the result with 'git commit -c %s'",
+ find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
}
static void write_message(struct strbuf *msgbuf, const char *filename)
return write_ref_sha1(ref_lock, to, "cherry-pick");
}
-static void do_recursive_merge(struct commit *base, struct commit *next,
- const char *base_label, const char *next_label,
- unsigned char *head, struct strbuf *msgbuf,
- char *defmsg)
+static int do_recursive_merge(struct commit *base, struct commit *next,
+ const char *base_label, const char *next_label,
+ unsigned char *head, struct strbuf *msgbuf)
{
struct merge_options o;
struct tree *result, *next_tree, *base_tree, *head_tree;
i++;
}
}
- write_message(msgbuf, defmsg);
- fprintf(stderr, "Automatic %s failed.%s\n",
- me, help_msg());
- rerere(allow_rerere_auto);
- exit(1);
}
- write_message(msgbuf, defmsg);
- fprintf(stderr, "Finished one %s.\n", me);
+
+ return !clean;
+}
+
+/*
+ * If we are cherry-pick, and if the merge did not result in
+ * hand-editing, we will hit this commit and inherit the original
+ * author date and name.
+ * If we are revert, or if our cherry-pick results in a hand merge,
+ * we had better say that the current user is responsible for that.
+ */
+static int run_git_commit(const char *defmsg)
+{
+ /* 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 (signoff)
+ args[i++] = "-s";
+ if (!edit) {
+ args[i++] = "-F";
+ args[i++] = defmsg;
+ }
+ args[i] = NULL;
+
+ return run_command_v_opt(args, RUN_GIT_CMD);
}
static int do_pick_commit(void)
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
char *defmsg = NULL;
struct strbuf msgbuf = STRBUF_INIT;
+ int res;
if (no_commit) {
/*
}
}
- if (!strategy || !strcmp(strategy, "recursive") || action == REVERT)
- do_recursive_merge(base, next, base_label, next_label,
- head, &msgbuf, defmsg);
- else {
- int res;
+ if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) {
+ res = do_recursive_merge(base, next, base_label, next_label,
+ head, &msgbuf);
+ write_message(&msgbuf, defmsg);
+ } else {
struct commit_list *common = NULL;
struct commit_list *remotes = NULL;
+
write_message(&msgbuf, defmsg);
+
commit_list_insert(base, &common);
commit_list_insert(next, &remotes);
res = try_merge_command(strategy, common,
sha1_to_hex(head), remotes);
free_commit_list(common);
free_commit_list(remotes);
- if (res) {
- fprintf(stderr, "Automatic %s with strategy %s failed.%s\n",
- me, strategy, help_msg());
- rerere(allow_rerere_auto);
- exit(1);
- }
}
- free_message(&msg);
-
- /*
- *
- * If we are cherry-pick, and if the merge did not result in
- * hand-editing, we will hit this commit and inherit the original
- * author date and name.
- * If we are revert, or if our cherry-pick results in a hand merge,
- * we had better say that the current user is responsible for that.
- */
-
- if (!no_commit) {
- /* 6 is max possible length of our args array including NULL */
- const char *args[6];
- int res;
- int i = 0;
-
- args[i++] = "commit";
- args[i++] = "-n";
- if (signoff)
- args[i++] = "-s";
- if (!edit) {
- args[i++] = "-F";
- args[i++] = defmsg;
- }
- args[i] = NULL;
- res = run_command_v_opt(args, RUN_GIT_CMD);
- free(defmsg);
-
- return res;
+ if (res) {
+ error("could not %s %s... %s",
+ action == REVERT ? "revert" : "apply",
+ find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV),
+ msg.subject);
+ print_advice();
+ rerere(allow_rerere_auto);
+ } else {
+ if (!no_commit)
+ res = run_git_commit(defmsg);
}
+ free_message(&msg);
free(defmsg);
- return 0;
+ return res;
}
static void prepare_revs(struct rev_info *revs)
. ./test-lib.sh
+check_head_differs_from() {
+ head=$(git rev-parse --verify HEAD) &&
+ arg=$(git rev-parse --verify "$1") &&
+ test "$head" != "$arg"
+}
+
+check_head_equals() {
+ head=$(git rev-parse --verify HEAD) &&
+ arg=$(git rev-parse --verify "$1") &&
+ test "$head" = "$arg"
+}
+
test_expect_success setup '
echo first > file1 &&
git add file1 &&
'
test_expect_success 'cherry-pick first..fourth works' '
+ cat <<-\EOF >expected &&
+ [master OBJID] second
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ [master OBJID] third
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ [master OBJID] fourth
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ EOF
+
+ git checkout -f master &&
+ git reset --hard first &&
+ test_tick &&
+ git cherry-pick first..fourth >actual &&
+ git diff --quiet other &&
+ git diff --quiet HEAD other &&
+
+ sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy &&
+ test_cmp expected actual.fuzzy &&
+ check_head_differs_from fourth
+'
+
+test_expect_success 'cherry-pick --strategy resolve first..fourth works' '
+ cat <<-\EOF >expected &&
+ Trying simple merge.
+ [master OBJID] second
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ Trying simple merge.
+ [master OBJID] third
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ Trying simple merge.
+ [master OBJID] fourth
+ Author: A U Thor <author@example.com>
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+ EOF
+
git checkout -f master &&
git reset --hard first &&
test_tick &&
- git cherry-pick first..fourth &&
+ git cherry-pick --strategy resolve first..fourth >actual &&
git diff --quiet other &&
git diff --quiet HEAD other &&
- test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
+ sed -e "s/$_x05[0-9a-f][0-9a-f]/OBJID/" <actual >actual.fuzzy &&
+ test_cmp expected actual.fuzzy &&
+ check_head_differs_from fourth
'
test_expect_success 'cherry-pick --ff first..fourth works' '
git cherry-pick --ff first..fourth &&
git diff --quiet other &&
git diff --quiet HEAD other &&
- test "$(git rev-parse --verify HEAD)" = "$(git rev-parse --verify fourth)"
+ check_head_equals fourth
'
test_expect_success 'cherry-pick -n first..fourth works' '
git cherry-pick -3 fourth &&
git diff --quiet other &&
git diff --quiet HEAD other &&
- test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
+ check_head_differs_from fourth
'
test_expect_success 'cherry-pick --stdin works' '
git rev-list --reverse first..fourth | git cherry-pick --stdin &&
git diff --quiet other &&
git diff --quiet HEAD other &&
- test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
+ check_head_differs_from fourth
'
test_done