Skip to content

Commit 82433cd

Browse files
jrngitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b8c7469 commit 82433cd

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

branch.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ void create_branch(const char *head,
241241
void remove_branch_state(void)
242242
{
243243
unlink(git_path("CHERRY_PICK_HEAD"));
244+
unlink(git_path("REVERT_HEAD"));
244245
unlink(git_path("MERGE_HEAD"));
245246
unlink(git_path("MERGE_RR"));
246247
unlink(git_path("MERGE_MSG"));

builtin/commit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
15141514
}
15151515

15161516
unlink(git_path("CHERRY_PICK_HEAD"));
1517+
unlink(git_path("REVERT_HEAD"));
15171518
unlink(git_path("MERGE_HEAD"));
15181519
unlink(git_path("MERGE_MSG"));
15191520
unlink(git_path("MERGE_MODE"));

builtin/revert.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,15 +289,15 @@ static char *get_encoding(const char *message)
289289
return NULL;
290290
}
291291

292-
static void write_cherry_pick_head(struct commit *commit)
292+
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
293293
{
294294
const char *filename;
295295
int fd;
296296
struct strbuf buf = STRBUF_INIT;
297297

298298
strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
299299

300-
filename = git_path("CHERRY_PICK_HEAD");
300+
filename = git_path(pseudoref);
301301
fd = open(filename, O_WRONLY | O_CREAT, 0666);
302302
if (fd < 0)
303303
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)
597597
* write it at all.
598598
*/
599599
if (opts->action == CHERRY_PICK && !opts->no_commit && (res == 0 || res == 1))
600-
write_cherry_pick_head(commit);
600+
write_cherry_pick_head(commit, "CHERRY_PICK_HEAD");
601+
if (opts->action == REVERT && ((opts->no_commit && res == 0) || res == 1))
602+
write_cherry_pick_head(commit, "REVERT_HEAD");
601603

602604
if (res) {
603605
error(opts->action == REVERT

t/t3507-cherry-pick-conflict.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,60 @@ test_expect_success 'revert also handles conflicts sanely' '
253253
test_cmp expected actual
254254
'
255255

256+
test_expect_success 'failed revert sets REVERT_HEAD' '
257+
pristine_detach initial &&
258+
test_must_fail git revert picked &&
259+
test_cmp_rev picked REVERT_HEAD
260+
'
261+
262+
test_expect_success 'successful revert does not set REVERT_HEAD' '
263+
pristine_detach base &&
264+
git revert base &&
265+
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
266+
test_must_fail git rev-parse --verify REVERT_HEAD
267+
'
268+
269+
test_expect_success 'revert --no-commit sets REVERT_HEAD' '
270+
pristine_detach base &&
271+
git revert --no-commit base &&
272+
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
273+
test_cmp_rev base REVERT_HEAD
274+
'
275+
276+
test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
277+
pristine_detach base &&
278+
echo foo > foo &&
279+
test_must_fail git revert base &&
280+
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
281+
test_must_fail git rev-parse --verify REVERT_HEAD
282+
'
283+
284+
test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
285+
pristine_detach initial &&
286+
(
287+
GIT_CHERRY_PICK_HELP="and then do something else" &&
288+
GIT_REVERT_HELP="and then do something else, again" &&
289+
export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
290+
test_must_fail git revert picked
291+
) &&
292+
test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
293+
test_cmp_rev picked REVERT_HEAD
294+
'
295+
296+
test_expect_success 'git reset clears REVERT_HEAD' '
297+
pristine_detach initial &&
298+
test_must_fail git revert picked &&
299+
git reset &&
300+
test_must_fail git rev-parse --verify REVERT_HEAD
301+
'
302+
303+
test_expect_success 'failed commit does not clear REVERT_HEAD' '
304+
pristine_detach initial &&
305+
test_must_fail git revert picked &&
306+
test_must_fail git commit &&
307+
test_cmp_rev picked REVERT_HEAD
308+
'
309+
256310
test_expect_success 'revert conflict, diff3 -m style' '
257311
pristine_detach initial &&
258312
git config merge.conflictstyle diff3 &&

0 commit comments

Comments
 (0)