Merge branch 'pw/rebase-i-regression-fix-tests'
authorJunio C Hamano <gitster@pobox.com>
Fri, 30 Jun 2017 20:45:21 +0000 (13:45 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 30 Jun 2017 20:45:21 +0000 (13:45 -0700)
Fix a recent regression to "git rebase -i" and add tests that would
have caught it and others.

* pw/rebase-i-regression-fix-tests:
t3420: fix under GETTEXT_POISON build
rebase: add more regression tests for console output
rebase: add regression tests for console output
rebase -i: add test for reflog message
sequencer: print autostash messages to stderr

1  2 
git-rebase.sh
sequencer.c
t/t3404-rebase-interactive.sh
diff --combined git-rebase.sh
index db1deed8464f0643763ed6e3c5e54221cad8c985,3b0448dd3acce169d1d18cca58f8a66ae9d56959..2cf73b88e8e83ca34b9eb319dbc2b0a220139b0f
@@@ -34,7 -34,6 +34,7 @@@ root!              rebase all reachabl
  autosquash         move commits that begin with squash!/fixup! under -i
  committer-date-is-author-date! passed to 'git am'
  ignore-date!       passed to 'git am'
 +signoff            passed to 'git am'
  whitespace=!       passed to 'git apply'
  ignore-whitespace! passed to 'git apply'
  C=!                passed to 'git apply'
@@@ -166,14 -165,14 +166,14 @@@ apply_autostash () 
                stash_sha1=$(cat "$state_dir/autostash")
                if git stash apply $stash_sha1 2>&1 >/dev/null
                then
-                       echo "$(gettext 'Applied autostash.')"
+                       echo "$(gettext 'Applied autostash.')" >&2
                else
                        git stash store -m "autostash" -q $stash_sha1 ||
                        die "$(eval_gettext "Cannot store \$stash_sha1")"
                        gettext 'Applying autostash resulted in conflicts.
  Your changes are safe in the stash.
  You can run "git stash pop" or "git stash drop" at any time.
- '
+ ' >&2
                fi
        fi
  }
@@@ -322,7 -321,7 +322,7 @@@ d
        --ignore-whitespace)
                git_am_opt="$git_am_opt $1"
                ;;
 -      --committer-date-is-author-date|--ignore-date)
 +      --committer-date-is-author-date|--ignore-date|--signoff|--no-signoff)
                git_am_opt="$git_am_opt $1"
                force_rebase=t
                ;;
diff --combined sequencer.c
index 98cdfe74fdac47da5ca2f640ae8ae2dbaa6051d4,fd75d51bd698dd56abea52be6576c791cb2273a3..3010faf86398697469e903318a35421d911acb23
@@@ -1,5 -1,4 +1,5 @@@
  #include "cache.h"
 +#include "config.h"
  #include "lockfile.h"
  #include "sequencer.h"
  #include "dir.h"
@@@ -345,7 -344,7 +345,7 @@@ static int read_oneliner(struct strbuf 
  
  static struct tree *empty_tree(void)
  {
 -      return lookup_tree(EMPTY_TREE_SHA1_BIN);
 +      return lookup_tree(&empty_tree_oid);
  }
  
  static int error_dirty_index(struct replay_opts *opts)
@@@ -375,7 -374,7 +375,7 @@@ static void update_abort_safety_file(vo
                write_file(git_path_abort_safety_file(), "%s", "");
  }
  
 -static int fast_forward_to(const unsigned char *to, const unsigned char *from,
 +static int fast_forward_to(const struct object_id *to, const struct object_id *from,
                        int unborn, struct replay_opts *opts)
  {
        struct ref_transaction *transaction;
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
            ref_transaction_update(transaction, "HEAD",
 -                                 to, unborn ? null_sha1 : from,
 +                                 to->hash, unborn ? null_sha1 : from->hash,
                                   0, sb.buf, &err) ||
            ref_transaction_commit(transaction, &err)) {
                ref_transaction_free(transaction);
@@@ -427,7 -426,7 +427,7 @@@ void append_conflicts_hint(struct strbu
  
  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 object_id *head, struct strbuf *msgbuf,
                              struct replay_opts *opts)
  {
        struct merge_options o;
  
        if (active_cache_changed &&
            write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
 -              /* TRANSLATORS: %s will be "revert", "cherry-pick" or
 +              /*
 +               * TRANSLATORS: %s will be "revert", "cherry-pick" or
                 * "rebase -i".
                 */
                return error(_("%s: Unable to write new index file"),
  
  static int is_index_unchanged(void)
  {
 -      unsigned char head_sha1[20];
 +      struct object_id head_oid;
        struct commit *head_commit;
  
 -      if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL))
 +      if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL))
                return error(_("could not resolve HEAD commit\n"));
  
 -      head_commit = lookup_commit(head_sha1);
 +      head_commit = lookup_commit(&head_oid);
  
        /*
         * If head_commit is NULL, check_commit, called from
                if (cache_tree_update(&the_index, 0))
                        return error(_("unable to update cache tree\n"));
  
 -      return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.oid.hash);
 +      return !oidcmp(&active_cache_tree->oid,
 +                     &head_commit->tree->object.oid);
  }
  
  static int write_author_script(const char *message)
@@@ -605,12 -602,6 +605,12 @@@ N_("you have staged changes in your wor
  "\n"
  "  git rebase --continue\n");
  
 +#define ALLOW_EMPTY (1<<0)
 +#define EDIT_MSG    (1<<1)
 +#define AMEND_MSG   (1<<2)
 +#define CLEANUP_MSG (1<<3)
 +#define VERIFY_MSG  (1<<4)
 +
  /*
   * 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 metadata.
   */
  static int run_git_commit(const char *defmsg, struct replay_opts *opts,
 -                        int allow_empty, int edit, int amend,
 -                        int cleanup_commit_message)
 +                        unsigned int flags)
  {
        struct child_process cmd = CHILD_PROCESS_INIT;
        const char *value;
        cmd.git_cmd = 1;
  
        if (is_rebase_i(opts)) {
 -              if (!edit) {
 +              if (!(flags & EDIT_MSG)) {
                        cmd.stdout_to_stderr = 1;
                        cmd.err = -1;
                }
        }
  
        argv_array_push(&cmd.args, "commit");
 -      argv_array_push(&cmd.args, "-n");
  
 -      if (amend)
 +      if (!(flags & VERIFY_MSG))
 +              argv_array_push(&cmd.args, "-n");
 +      if ((flags & AMEND_MSG))
                argv_array_push(&cmd.args, "--amend");
        if (opts->gpg_sign)
                argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
                argv_array_push(&cmd.args, "-s");
        if (defmsg)
                argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 -      if (cleanup_commit_message)
 +      if ((flags & CLEANUP_MSG))
                argv_array_push(&cmd.args, "--cleanup=strip");
 -      if (edit)
 +      if ((flags & EDIT_MSG))
                argv_array_push(&cmd.args, "-e");
 -      else if (!cleanup_commit_message &&
 +      else if (!(flags & CLEANUP_MSG) &&
                 !opts->signoff && !opts->record_origin &&
                 git_config_get_value("commit.cleanup", &value))
                argv_array_push(&cmd.args, "--cleanup=verbatim");
  
 -      if (allow_empty)
 +      if ((flags & ALLOW_EMPTY))
                argv_array_push(&cmd.args, "--allow-empty");
  
        if (opts->allow_empty_message)
@@@ -837,13 -828,13 +837,13 @@@ static int update_squash_messages(enum 
                strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
                strbuf_release(&header);
        } else {
 -              unsigned char head[20];
 +              struct object_id head;
                struct commit *head_commit;
                const char *head_message, *body;
  
 -              if (get_sha1("HEAD", head))
 +              if (get_oid("HEAD", &head))
                        return error(_("need a HEAD to fixup"));
 -              if (!(head_commit = lookup_commit_reference(head)))
 +              if (!(head_commit = lookup_commit_reference(&head)))
                        return error(_("could not read HEAD"));
                if (!(head_message = get_commit_buffer(head_commit, NULL)))
                        return error(_("could not read HEAD's commit message"));
@@@ -900,8 -891,8 +900,8 @@@ static void flush_rewritten_pending(voi
        FILE *out;
  
        if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), 82) > 0 &&
 -                      !get_sha1("HEAD", newsha1) &&
 -                      (out = fopen(rebase_path_rewritten_list(), "a"))) {
 +          !get_sha1("HEAD", newsha1) &&
 +          (out = fopen_or_warn(rebase_path_rewritten_list(), "a"))) {
                char *bol = buf.buf, *eol;
  
                while (*bol) {
  
  static void record_in_rewritten(struct object_id *oid,
                enum todo_command next_command) {
 -      FILE *out = fopen(rebase_path_rewritten_pending(), "a");
 +      FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
  
        if (!out)
                return;
  static int do_pick_commit(enum todo_command command, struct commit *commit,
                struct replay_opts *opts, int final_fixup)
  {
 -      int edit = opts->edit, cleanup_commit_message = 0;
 -      const char *msg_file = edit ? NULL : git_path_merge_msg();
 -      unsigned char head[20];
 +      unsigned int flags = opts->edit ? EDIT_MSG : 0;
 +      const char *msg_file = opts->edit ? NULL : git_path_merge_msg();
 +      struct object_id head;
        struct commit *base, *next, *parent;
        const char *base_label, *next_label;
        struct commit_message msg = { NULL, NULL, NULL, NULL };
        struct strbuf msgbuf = STRBUF_INIT;
 -      int res, unborn = 0, amend = 0, allow = 0;
 +      int res, unborn = 0, allow;
  
        if (opts->no_commit) {
                /*
                 * that represents the "current" state for merge-recursive
                 * to work on.
                 */
 -              if (write_cache_as_tree(head, 0, NULL))
 +              if (write_cache_as_tree(head.hash, 0, NULL))
                        return error(_("your index file is unmerged."));
        } else {
 -              unborn = get_sha1("HEAD", head);
 +              unborn = get_oid("HEAD", &head);
                if (unborn)
 -                      hashcpy(head, EMPTY_TREE_SHA1_BIN);
 +                      oidcpy(&head, &empty_tree_oid);
                if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0))
                        return error_dirty_index(opts);
        }
                        oid_to_hex(&commit->object.oid));
  
        if (opts->allow_ff && !is_fixup(command) &&
 -          ((parent && !hashcmp(parent->object.oid.hash, head)) ||
 +          ((parent && !oidcmp(&parent->object.oid, &head)) ||
             (!parent && unborn))) {
                if (is_rebase_i(opts))
                        write_author_script(msg.message);
 -              res = fast_forward_to(commit->object.oid.hash, head, unborn,
 +              res = fast_forward_to(&commit->object.oid, &head, unborn,
                        opts);
                if (res || command != TODO_REWORD)
                        goto leave;
 -              edit = amend = 1;
 +              flags |= EDIT_MSG | AMEND_MSG;
 +              if (command == TODO_REWORD)
 +                      flags |= VERIFY_MSG;
                msg_file = NULL;
                goto fast_forward_edit;
        }
                        strbuf_addstr(&msgbuf, p);
  
                if (opts->record_origin) {
 +                      strbuf_complete_line(&msgbuf);
                        if (!has_conforming_footer(&msgbuf, NULL, 0))
                                strbuf_addch(&msgbuf, '\n');
                        strbuf_addstr(&msgbuf, cherry_picked_prefix);
        }
  
        if (command == TODO_REWORD)
 -              edit = 1;
 +              flags |= EDIT_MSG | VERIFY_MSG;
        else if (is_fixup(command)) {
                if (update_squash_messages(command, commit, opts))
                        return -1;
 -              amend = 1;
 +              flags |= AMEND_MSG;
                if (!final_fixup)
                        msg_file = rebase_path_squash_msg();
                else if (file_exists(rebase_path_fixup_msg())) {
 -                      cleanup_commit_message = 1;
 +                      flags |= CLEANUP_MSG;
                        msg_file = rebase_path_fixup_msg();
                } else {
 -                      const char *dest = git_path("SQUASH_MSG");
 +                      const char *dest = git_path_squash_msg();
                        unlink(dest);
                        if (copy_file(dest, rebase_path_squash_msg(), 0666))
                                return error(_("could not rename '%s' to '%s'"),
                                             rebase_path_squash_msg(), dest);
 -                      unlink(git_path("MERGE_MSG"));
 +                      unlink(git_path_merge_msg());
                        msg_file = dest;
 -                      edit = 1;
 +                      flags |= EDIT_MSG;
                }
        }
  
                res = -1;
        else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
                res = do_recursive_merge(base, next, base_label, next_label,
 -                                       head, &msgbuf, opts);
 +                                       &head, &msgbuf, opts);
                if (res < 0)
                        return res;
                res |= write_message(msgbuf.buf, msgbuf.len,
                commit_list_insert(next, &remotes);
                res |= try_merge_command(opts->strategy,
                                         opts->xopts_nr, (const char **)opts->xopts,
 -                                      common, sha1_to_hex(head), remotes);
 +                                      common, oid_to_hex(&head), remotes);
                free_commit_list(common);
                free_commit_list(remotes);
        }
        if (allow < 0) {
                res = allow;
                goto leave;
 -      }
 +      } else if (allow)
 +              flags |= ALLOW_EMPTY;
        if (!opts->no_commit)
  fast_forward_edit:
 -              res = run_git_commit(msg_file, opts, allow, edit, amend,
 -                                   cleanup_commit_message);
 +              res = run_git_commit(msg_file, opts, flags);
  
        if (!res && final_fixup) {
                unlink(rebase_path_fixup_msg());
@@@ -1204,7 -1192,6 +1204,7 @@@ struct todo_list 
        struct todo_item *items;
        int nr, alloc, current;
        int done_nr, total_nr;
 +      struct stat_data stat;
  };
  
  #define TODO_LIST_INIT { STRBUF_INIT }
  static void todo_list_release(struct todo_list *todo_list)
  {
        strbuf_release(&todo_list->buf);
 -      free(todo_list->items);
 -      todo_list->items = NULL;
 +      FREE_AND_NULL(todo_list->items);
        todo_list->nr = todo_list->alloc = 0;
  }
  
@@@ -1224,7 -1212,7 +1224,7 @@@ static struct todo_item *append_new_tod
  
  static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
  {
 -      unsigned char commit_sha1[20];
 +      struct object_id commit_oid;
        char *end_of_object_name;
        int i, saved, status, padding;
  
        end_of_object_name = (char *) bol + strcspn(bol, " \t\n");
        saved = *end_of_object_name;
        *end_of_object_name = '\0';
 -      status = get_sha1(bol, commit_sha1);
 +      status = get_oid(bol, &commit_oid);
        *end_of_object_name = saved;
  
        item->arg = end_of_object_name + strspn(end_of_object_name, " \t");
        if (status < 0)
                return -1;
  
 -      item->commit = lookup_commit_reference(commit_sha1);
 +      item->commit = lookup_commit_reference(&commit_oid);
        return !item->commit;
  }
  
@@@ -1334,7 -1322,6 +1334,7 @@@ static int count_commands(struct todo_l
  static int read_populate_todo(struct todo_list *todo_list,
                        struct replay_opts *opts)
  {
 +      struct stat st;
        const char *todo_file = get_todo_path(opts);
        int fd, res;
  
        }
        close(fd);
  
 +      res = stat(todo_file, &st);
 +      if (res)
 +              return error(_("could not stat '%s'"), todo_file);
 +      fill_stat_data(&todo_list->stat, &st);
 +
        res = parse_insn_buffer(todo_list->buf.buf, todo_list);
        if (res) {
                if (is_rebase_i(opts))
  
        if (is_rebase_i(opts)) {
                struct todo_list done = TODO_LIST_INIT;
 -              FILE *f = fopen(rebase_path_msgtotal(), "w");
 +              FILE *f = fopen_or_warn(rebase_path_msgtotal(), "w");
  
                if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
                                !parse_insn_buffer(done.buf.buf, &done))
@@@ -1830,10 -1812,10 +1830,10 @@@ static int error_failed_squash(struct c
                return error(_("could not rename '%s' to '%s'"),
                        rebase_path_squash_msg(), rebase_path_message());
        unlink(rebase_path_fixup_msg());
 -      unlink(git_path("MERGE_MSG"));
 -      if (copy_file(git_path("MERGE_MSG"), rebase_path_message(), 0666))
 +      unlink(git_path_merge_msg());
 +      if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
                return error(_("could not copy '%s' to '%s'"),
 -                           rebase_path_message(), git_path("MERGE_MSG"));
 +                           rebase_path_message(), git_path_merge_msg());
        return error_with_patch(commit, subject, subject_len, opts, 1, 0);
  }
  
@@@ -1922,7 -1904,7 +1922,7 @@@ static int apply_autostash(struct repla
        argv_array_push(&child.args, "apply");
        argv_array_push(&child.args, stash_sha1.buf);
        if (!run_command(&child))
-               printf(_("Applied autostash.\n"));
+               fprintf(stderr, _("Applied autostash.\n"));
        else {
                struct child_process store = CHILD_PROCESS_INIT;
  
                if (run_command(&store))
                        ret = error(_("cannot store %s"), stash_sha1.buf);
                else
-                       printf(_("Applying autostash resulted in conflicts.\n"
-                               "Your changes are safe in the stash.\n"
-                               "You can run \"git stash pop\" or"
-                               " \"git stash drop\" at any time.\n"));
+                       fprintf(stderr,
+                               _("Applying autostash resulted in conflicts.\n"
+                                 "Your changes are safe in the stash.\n"
+                                 "You can run \"git stash pop\" or"
+                                 " \"git stash drop\" at any time.\n"));
        }
  
        strbuf_release(&stash_sha1);
@@@ -2040,25 -2023,10 +2041,25 @@@ static int pick_commits(struct todo_lis
                } else if (item->command == TODO_EXEC) {
                        char *end_of_arg = (char *)(item->arg + item->arg_len);
                        int saved = *end_of_arg;
 +                      struct stat st;
  
                        *end_of_arg = '\0';
                        res = do_exec(item->arg);
                        *end_of_arg = saved;
 +
 +                      /* Reread the todo file if it has changed. */
 +                      if (res)
 +                              ; /* fall through */
 +                      else if (stat(get_todo_path(opts), &st))
 +                              res = error_errno(_("could not stat '%s'"),
 +                                                get_todo_path(opts));
 +                      else if (match_stat_data(&todo_list->stat, &st)) {
 +                              todo_list_release(todo_list);
 +                              if (read_populate_todo(todo_list, opts))
 +                                      res = -1; /* message was printed */
 +                              /* `current` will be incremented below */
 +                              todo_list->current = -1;
 +                      }
                } else if (!is_noop(item->command))
                        return error(_("unknown command %d"), item->command);
  
@@@ -2130,8 -2098,8 +2131,8 @@@ cleanup_head_ref
                        if (read_oneliner(&buf, rebase_path_orig_head(), 0) &&
                            !get_sha1(buf.buf, orig.hash) &&
                            !get_sha1("HEAD", head.hash)) {
 -                              diff_tree_sha1(orig.hash, head.hash,
 -                                             "", &log_tree_opt.diffopt);
 +                              diff_tree_oid(&orig, &head, "",
 +                                            &log_tree_opt.diffopt);
                                log_tree_diff_flush(&log_tree_opt);
                        }
                }
@@@ -2190,12 -2158,12 +2191,12 @@@ static int continue_single_pick(void
  
  static int commit_staged_changes(struct replay_opts *opts)
  {
 -      int amend = 0;
 +      unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
  
        if (has_unstaged_changes(1))
                return error(_("cannot rebase: You have unstaged changes."));
        if (!has_uncommitted_changes(0)) {
 -              const char *cherry_pick_head = git_path("CHERRY_PICK_HEAD");
 +              const char *cherry_pick_head = git_path_cherry_pick_head();
  
                if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
                        return error(_("could not remove CHERRY_PICK_HEAD"));
                                       "--continue' again."));
  
                strbuf_release(&rev);
 -              amend = 1;
 +              flags |= AMEND_MSG;
        }
  
 -      if (run_git_commit(rebase_path_message(), opts, 1, 1, amend, 0))
 +      if (run_git_commit(rebase_path_message(), opts, flags))
                return error(_("could not commit staged changes."));
        unlink(rebase_path_amend());
        return 0;
@@@ -2286,7 -2254,7 +2287,7 @@@ static int single_pick(struct commit *c
  int sequencer_pick_revisions(struct replay_opts *opts)
  {
        struct todo_list todo_list = TODO_LIST_INIT;
 -      unsigned char sha1[20];
 +      struct object_id oid;
        int i, res;
  
        assert(opts->revs);
                return -1;
  
        for (i = 0; i < opts->revs->pending.nr; i++) {
 -              unsigned char sha1[20];
 +              struct object_id oid;
                const char *name = opts->revs->pending.objects[i].name;
  
                /* This happens when using --stdin. */
                if (!strlen(name))
                        continue;
  
 -              if (!get_sha1(name, sha1)) {
 -                      if (!lookup_commit_reference_gently(sha1, 1)) {
 -                              enum object_type type = sha1_object_info(sha1, NULL);
 +              if (!get_oid(name, &oid)) {
 +                      if (!lookup_commit_reference_gently(&oid, 1)) {
 +                              enum object_type type = sha1_object_info(oid.hash, NULL);
                                return error(_("%s: can't cherry-pick a %s"),
                                        name, typename(type));
                        }
        if (walk_revs_populate_todo(&todo_list, opts) ||
                        create_seq_dir() < 0)
                return -1;
 -      if (get_sha1("HEAD", sha1) && (opts->action == REPLAY_REVERT))
 +      if (get_oid("HEAD", &oid) && (opts->action == REPLAY_REVERT))
                return error(_("can't revert as initial commit"));
 -      if (save_head(sha1_to_hex(sha1)))
 +      if (save_head(oid_to_hex(&oid)))
                return -1;
        if (save_opts(opts))
                return -1;
@@@ -2363,9 -2331,6 +2364,9 @@@ void append_signoff(struct strbuf *msgb
                                getenv("GIT_COMMITTER_EMAIL")));
        strbuf_addch(&sob, '\n');
  
 +      if (!ignore_footer)
 +              strbuf_complete_line(msgbuf);
 +
        /*
         * If the whole message buffer is equal to the sob, pretend that we
         * found a conforming footer with a matching sob
                         * the title and body to be filled in by the user.
                         */
                        append_newlines = "\n\n";
 -              } else if (msgbuf->buf[len - 1] != '\n') {
 -                      /*
 -                       * Incomplete line.  Complete the line and add a
 -                       * blank one so that there is an empty line between
 -                       * the message body and the sob.
 -                       */
 -                      append_newlines = "\n\n";
                } else if (len == 1) {
                        /*
                         * Buffer contains a single newline.  Add another
index 5bd0275930b715c25507fc9744c8946e7f73900b,5403b4ba01b908230b67bb0a46d7073f4e99bd10..37821d245433f757fa13f0a3e27da0312bebb7db
@@@ -169,6 -169,13 +169,13 @@@ test_expect_success 'reflog for the bra
        test $(git rev-parse branch1@{1}) = $(git rev-parse original-branch1)
  '
  
+ test_expect_success 'reflog for the branch shows correct finish message' '
+       printf "rebase -i (finish): refs/heads/branch1 onto %s\n" \
+               "$(git rev-parse branch2)" >expected &&
+       git log -g --pretty=%gs -1 refs/heads/branch1 >actual &&
+       test_cmp expected actual
+ '
  test_expect_success 'exchange two commits' '
        set_fake_editor &&
        FAKE_LINES="2 1" git rebase -i HEAD~2 &&
@@@ -366,7 -373,7 +373,7 @@@ test_expect_success 'verbose flag is he
        grep "^ file1 | 2 +-$" output
  '
  
 -test_expect_success 'multi-squash only fires up editor once' '
 +test_expect_success C_LOCALE_OUTPUT 'multi-squash only fires up editor once' '
        base=$(git rev-parse HEAD~4) &&
        set_fake_editor &&
        FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \
        test 1 = $(git show | grep ONCE | wc -l)
  '
  
 -test_expect_success 'multi-fixup does not fire up editor' '
 +test_expect_success C_LOCALE_OUTPUT 'multi-fixup does not fire up editor' '
        git checkout -b multi-fixup E &&
        base=$(git rev-parse HEAD~4) &&
        set_fake_editor &&
  ONCE
  EOF
  
 -test_expect_success 'squash and fixup generate correct log messages' '
 +test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messages' '
        git checkout -b squash-fixup E &&
        base=$(git rev-parse HEAD~4) &&
        set_fake_editor &&
        git branch -D squash-fixup
  '
  
 -test_expect_success 'squash ignores comments' '
 +test_expect_success C_LOCALE_OUTPUT 'squash ignores comments' '
        git checkout -b skip-comments E &&
        base=$(git rev-parse HEAD~4) &&
        set_fake_editor &&
        git branch -D skip-comments
  '
  
 -test_expect_success 'squash ignores blank lines' '
 +test_expect_success C_LOCALE_OUTPUT 'squash ignores blank lines' '
        git checkout -b skip-blank-lines E &&
        base=$(git rev-parse HEAD~4) &&
        set_fake_editor &&
@@@ -860,7 -867,7 +867,7 @@@ test_expect_success 'rebase -ix with se
        test_cmp expected actual
  '
  
 -test_expect_success 'rebase -ix with --autosquash' '
 +test_expect_success C_LOCALE_OUTPUT 'rebase -ix with --autosquash' '
        git reset --hard execute &&
        git checkout -b autosquash &&
        echo second >second.txt &&
@@@ -943,7 -950,7 +950,7 @@@ test_expect_success 'rebase -i --root f
        test 0 = $(git cat-file commit HEAD | grep -c ^parent\ )
  '
  
 -test_expect_success 'rebase --edit-todo does not works on non-interactive rebase' '
 +test_expect_success C_LOCALE_OUTPUT 'rebase --edit-todo does not work on non-interactive rebase' '
        git reset --hard &&
        git checkout conflict-branch &&
        set_fake_editor &&