summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Nieder <jrnieder@gmail.com>2011-11-22 05:17:36 -0600
committerJunio C Hamano <gitster@pobox.com>2011-11-22 13:34:44 -0800
commit82433cdf4d888639cecddeca162d619cf370417e (patch)
treef079ee84d7364d734bfeb24ffc17b1451a26893c
parentb8c74690b20b7c4dd405f71d63bab325447356da (diff)
downloadgit-82433cdf4d888639cecddeca162d619cf370417e.tar.gz
revert: write REVERT_HEAD pseudoref during conflicted revert
When conflicts are encountered while reverting a commit, it can be handy to have the name of that commit easily available. For example, to produce a copy of the patch to refer to while resolving conflicts: $ git revert 2eceb2a8 error: could not revert 2eceb2a8... awesome, buggy feature $ git show -R REVERT_HEAD >the-patch $ edit $(git diff --name-only) Set a REVERT_HEAD pseudoref when "git revert" does not make a commit, for cases like this. This also makes it possible for scripts to distinguish between a revert that encountered conflicts and other sources of an unmerged index. After successfully committing, resetting with "git reset", or moving to another commit with "git checkout" or "git reset", the pseudoref is no longer useful, so remove it. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--branch.c1
-rw-r--r--builtin/commit.c1
-rw-r--r--builtin/revert.c8
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh54
4 files changed, 61 insertions, 3 deletions
diff --git a/branch.c b/branch.c
index d8098762f6..025a97be02 100644
--- a/branch.c
+++ b/branch.c
@@ -241,6 +241,7 @@ void create_branch(const char *head,
void remove_branch_state(void)
{
unlink(git_path("CHERRY_PICK_HEAD"));
+ unlink(git_path("REVERT_HEAD"));
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_RR"));
unlink(git_path("MERGE_MSG"));
diff --git a/builtin/commit.c b/builtin/commit.c
index c46f2d18e1..8f2bebecf3 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1514,6 +1514,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
}
unlink(git_path("CHERRY_PICK_HEAD"));
+ unlink(git_path("REVERT_HEAD"));
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_MSG"));
unlink(git_path("MERGE_MODE"));
diff --git a/builtin/revert.c b/builtin/revert.c
index 1d112e4ce4..f5ba67a505 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -289,7 +289,7 @@ static char *get_encoding(const char *message)
return NULL;
}
-static void write_cherry_pick_head(struct commit *commit)
+static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
{
const char *filename;
int fd;
@@ -297,7 +297,7 @@ static void write_cherry_pick_head(struct commit *commit)
strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
- filename = git_path("CHERRY_PICK_HEAD");
+ filename = git_path(pseudoref);
fd = open(filename, O_WRONLY | O_CREAT, 0666);
if (fd < 0)
die_errno(_("Could not open '%s' for writing"), filename);
@@ -597,7 +597,9 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
* write it at all.
*/
if (opts->action == CHERRY_PICK && !opts->no_commit && (res == 0 || res == 1))
- write_cherry_pick_head(commit);
+ write_cherry_pick_head(commit, "CHERRY_PICK_HEAD");
+ if (opts->action == REVERT && ((opts->no_commit && res == 0) || res == 1))
+ write_cherry_pick_head(commit, "REVERT_HEAD");
if (res) {
error(opts->action == REVERT
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index cb45574a7b..ee1659c178 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -253,6 +253,60 @@ test_expect_success 'revert also handles conflicts sanely' '
test_cmp expected actual
'
+test_expect_success 'failed revert sets REVERT_HEAD' '
+ pristine_detach initial &&
+ test_must_fail git revert picked &&
+ test_cmp_rev picked REVERT_HEAD
+'
+
+test_expect_success 'successful revert does not set REVERT_HEAD' '
+ pristine_detach base &&
+ git revert base &&
+ test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+ test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'revert --no-commit sets REVERT_HEAD' '
+ pristine_detach base &&
+ git revert --no-commit base &&
+ test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+ test_cmp_rev base REVERT_HEAD
+'
+
+test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
+ pristine_detach base &&
+ echo foo > foo &&
+ test_must_fail git revert base &&
+ test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+ test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
+ pristine_detach initial &&
+ (
+ GIT_CHERRY_PICK_HELP="and then do something else" &&
+ GIT_REVERT_HELP="and then do something else, again" &&
+ export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
+ test_must_fail git revert picked
+ ) &&
+ test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
+ test_cmp_rev picked REVERT_HEAD
+'
+
+test_expect_success 'git reset clears REVERT_HEAD' '
+ pristine_detach initial &&
+ test_must_fail git revert picked &&
+ git reset &&
+ test_must_fail git rev-parse --verify REVERT_HEAD
+'
+
+test_expect_success 'failed commit does not clear REVERT_HEAD' '
+ pristine_detach initial &&
+ test_must_fail git revert picked &&
+ test_must_fail git commit &&
+ test_cmp_rev picked REVERT_HEAD
+'
+
test_expect_success 'revert conflict, diff3 -m style' '
pristine_detach initial &&
git config merge.conflictstyle diff3 &&