replace: peel tag when passing a tag first to --graft

When passing a tag as the first argument to `git replace --graft`, it can be useful to accept it and use the underlying commit as a the commit that will be replaced. This already works for lightweight tags, but unfortunately for annotated tags we have been using the hash of the tag object instead of the hash of the underlying commit. Especially we would pass the hash of the tag object to replace_object_oid() where we would likely fail with an error like: "error: Objects must be of the same type. 'annotated_replaced_object' points to a replaced object of type 'tag' while 'replacement' points to a replacement object of type 'commit'." This patch fixes that by using the hash of the underlying commit when an annotated tag is passed. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed Mar 31, 2019 at 15:46 UTC ee521ec4cb09981c14ec32aca370b5ff5d15c4d9
2 files changed +18 -4
builtin/replace.c
+7 -4
@@ -477,15 +477,18 @@ static int create_graft(int argc, const char **argv, int force, int gentle)
477
478 strbuf_release(&buf);
479
480 - if (oideq(&old_oid, &new_oid)) {
480 + if (oideq(&commit->object.oid, &new_oid)) {
481 if (gentle) {
482 - warning(_("graft for '%s' unnecessary"), oid_to_hex(&old_oid));
482 + warning(_("graft for '%s' unnecessary"),
483 + oid_to_hex(&commit->object.oid));
484 return 0;
485 }
485 - return error(_("new commit is the same as the old one: '%s'"), oid_to_hex(&old_oid));
486 + return error(_("new commit is the same as the old one: '%s'"),
487 + oid_to_hex(&commit->object.oid));
488 }
489
488 - return replace_object_oid(old_ref, &old_oid, "replacement", &new_oid, force);
490 + return replace_object_oid(old_ref, &commit->object.oid,
491 + "replacement", &new_oid, force);
492 }
493
494 static int convert_graft_file(int force)
t/t6050-replace.sh
+11
@@ -417,6 +417,17 @@ test_expect_success '--graft using a tag as the new parent' '
417 git replace -d $HASH7
418 '
419
420 +test_expect_success '--graft using a tag as the replaced object' '
421 + git tag replaced_object $HASH7 &&
422 + git replace --graft replaced_object $HASH5 &&
423 + commit_has_parents $HASH7 $HASH5 &&
424 + git replace -d $HASH7 &&
425 + git tag -a -m "annotated replaced object tag" annotated_replaced_object $HASH7 &&
426 + git replace --graft annotated_replaced_object $HASH5 &&
427 + commit_has_parents $HASH7 $HASH5 &&
428 + git replace -d $HASH7
429 +'
430 +
431 test_expect_success GPG 'set up a signed commit' '
432 echo "line 17" >>hello &&
433 echo "line 18" >>hello &&