sequencer (rebase -i): update refs after a successful rebase
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Mon, 2 Jan 2017 15:27:53 +0000 (16:27 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Jan 2017 22:57:30 +0000 (14:57 -0800)
An interactive rebase operates on a detached HEAD (to keep the reflog
of the original branch relatively clean), and updates the branch only
at the end.

Now that the sequencer learns to perform interactive rebases, it also
needs to learn the trick to update the branch before removing the
directory containing the state of the interactive rebase.

We introduce a new head_ref variable in a wider scope than necessary at
the moment, to allow for a later patch that prints out "Successfully
rebased and updated <ref>".

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sequencer.c
index 6a840216b16fe55bdd116619aa0778eeb30f9295..80b2b2a975b8f836784639cdb9249f449e8195ac 100644 (file)
@@ -102,6 +102,8 @@ static GIT_PATH_FUNC(rebase_path_stopped_sha, "rebase-merge/stopped-sha")
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
+static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
+static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
 
 static inline int is_rebase_i(const struct replay_opts *opts)
 {
@@ -1784,12 +1786,53 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
        }
 
        if (is_rebase_i(opts)) {
-               struct strbuf buf = STRBUF_INIT;
+               struct strbuf head_ref = STRBUF_INIT, buf = STRBUF_INIT;
 
                /* Stopped in the middle, as planned? */
                if (todo_list->current < todo_list->nr)
                        return 0;
 
+               if (read_oneliner(&head_ref, rebase_path_head_name(), 0) &&
+                               starts_with(head_ref.buf, "refs/")) {
+                       unsigned char head[20], orig[20];
+                       int res;
+
+                       if (get_sha1("HEAD", head)) {
+                               res = error(_("cannot read HEAD"));
+cleanup_head_ref:
+                               strbuf_release(&head_ref);
+                               strbuf_release(&buf);
+                               return res;
+                       }
+                       if (!read_oneliner(&buf, rebase_path_orig_head(), 0) ||
+                                       get_sha1_hex(buf.buf, orig)) {
+                               res = error(_("could not read orig-head"));
+                               goto cleanup_head_ref;
+                       }
+                       strbuf_addf(&buf, "rebase -i (finish): %s onto ",
+                               head_ref.buf);
+                       if (!read_oneliner(&buf, rebase_path_onto(), 0)) {
+                               res = error(_("could not read 'onto'"));
+                               goto cleanup_head_ref;
+                       }
+                       if (update_ref(buf.buf, head_ref.buf, head, orig,
+                                       REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) {
+                               res = error(_("could not update %s"),
+                                       head_ref.buf);
+                               goto cleanup_head_ref;
+                       }
+                       strbuf_reset(&buf);
+                       strbuf_addf(&buf,
+                               "rebase -i (finish): returning to %s",
+                               head_ref.buf);
+                       if (create_symref("HEAD", head_ref.buf, buf.buf)) {
+                               res = error(_("could not update HEAD to %s"),
+                                       head_ref.buf);
+                               goto cleanup_head_ref;
+                       }
+                       strbuf_reset(&buf);
+               }
+
                if (opts->verbose) {
                        struct rev_info log_tree_opt;
                        struct object_id orig, head;
@@ -1810,6 +1853,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
                        }
                }
                strbuf_release(&buf);
+               strbuf_release(&head_ref);
        }
 
        /*