static void execute_commands(struct command *commands, const char *unpacker_error) { struct command *cmd; unsigned char sha1[20]; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "n/a (unpacker error)"; return; } cmd = commands; if (check_everything_connected(iterate_receive_command_list, 0, &cmd)) set_connectivity_errors(commands); if (run_receive_hook(commands, pre_receive_hook, 0)) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "pre-receive hook declined"; return; } check_aliased_updates(commands); free(head_name_to_free); head_name = head_name_to_free = resolve_refdup("HEAD", sha1, 0, NULL); for (cmd = commands; cmd; cmd = cmd->next) if (!cmd->skip_update) cmd->error_string = update(cmd); }
static struct complete_reflogs *read_complete_reflog(const char *ref) { struct complete_reflogs *reflogs = xcalloc(1, sizeof(struct complete_reflogs)); reflogs->ref = xstrdup(ref); for_each_reflog_ent(ref, read_one_reflog, reflogs); if (reflogs->nr == 0) { struct object_id oid; const char *name; void *name_to_free; name = name_to_free = resolve_refdup(ref, RESOLVE_REF_READING, oid.hash, NULL); if (name) { for_each_reflog_ent(name, read_one_reflog, reflogs); free(name_to_free); } } if (reflogs->nr == 0) { char *refname = xstrfmt("refs/%s", ref); for_each_reflog_ent(refname, read_one_reflog, reflogs); if (reflogs->nr == 0) { free(refname); refname = xstrfmt("refs/heads/%s", ref); for_each_reflog_ent(refname, read_one_reflog, reflogs); } free(refname); } return reflogs; }
static int checkout(void) { unsigned char sha1[20]; char *head; struct lock_file *lock_file; struct unpack_trees_options opts; struct tree *tree; struct tree_desc t; int err = 0, fd; if (option_no_checkout) return 0; head = resolve_refdup("HEAD", sha1, 1, NULL); if (!head) { warning(_("remote HEAD refers to nonexistent ref, " "unable to checkout.\n")); return 0; } if (!strcmp(head, "HEAD")) { if (advice_detached_head) detach_advice(sha1_to_hex(sha1)); } else { if (prefixcmp(head, "refs/heads/")) die(_("HEAD not found below refs/heads!")); } free(head); /* We need to be in the new work tree for the checkout */ setup_work_tree(); lock_file = xcalloc(1, sizeof(struct lock_file)); fd = hold_locked_index(lock_file, 1); memset(&opts, 0, sizeof opts); opts.update = 1; opts.merge = 1; opts.fn = oneway_merge; opts.verbose_update = (option_verbosity >= 0); opts.src_index = &the_index; opts.dst_index = &the_index; tree = parse_tree_indirect(sha1); parse_tree(tree); init_tree_desc(&t, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts) < 0) die(_("unable to checkout working tree")); if (write_cache(fd, active_cache, active_nr) || commit_locked_index(lock_file)) die(_("unable to write new index file")); err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1), sha1_to_hex(sha1), "1", NULL); if (!err && option_recursive) err = run_command_v_opt(argv_submodule, RUN_GIT_CMD); return err; }
static void execute_commands(struct command *commands, const char *unpacker_error, struct shallow_info *si, const struct string_list *push_options) { struct check_connected_options opt = CHECK_CONNECTED_INIT; struct command *cmd; unsigned char sha1[20]; struct iterate_data data; struct async muxer; int err_fd = 0; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "unpacker error"; return; } if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; muxer.in = -1; if (!start_async(&muxer)) err_fd = muxer.in; /* ...else, continue without relaying sideband */ } data.cmds = commands; data.si = si; opt.err_fd = err_fd; opt.progress = err_fd && !quiet; if (check_connected(iterate_receive_command_list, &data, &opt)) set_connectivity_errors(commands, si); if (use_sideband) finish_async(&muxer); reject_updates_to_hidden(commands); if (run_receive_hook(commands, "pre-receive", 0, push_options)) { for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) cmd->error_string = "pre-receive hook declined"; } return; } check_aliased_updates(commands); free(head_name_to_free); head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL); if (use_atomic) execute_commands_atomic(commands, si); else execute_commands_non_atomic(commands, si); if (shallow_update) warn_if_skipped_connectivity_check(commands, si); }
int fmt_merge_msg(struct strbuf *in, struct strbuf *out, struct fmt_merge_msg_opts *opts) { int i = 0, pos = 0; unsigned char head_sha1[20]; const char *current_branch; void *current_branch_to_free; /* get current branch */ current_branch = current_branch_to_free = resolve_refdup("HEAD", head_sha1, 1, NULL); if (!current_branch) die("No current branch"); if (!prefixcmp(current_branch, "refs/heads/")) current_branch += 11; /* get a line */ while (pos < in->len) { int len; char *newline, *p = in->buf + pos; newline = strchr(p, '\n'); len = newline ? newline - p : strlen(p); pos += len + !!newline; i++; p[len] = 0; if (handle_line(p)) die ("Error in line %d: %.*s", i, len, p); } if (opts->add_title && srcs.nr) fmt_merge_msg_title(out, current_branch); if (origins.nr) fmt_merge_msg_sigs(out); if (opts->shortlog_len) { struct commit *head; struct rev_info rev; head = lookup_commit_or_die(head_sha1, "HEAD"); init_revisions(&rev, NULL); rev.commit_format = CMIT_FMT_ONELINE; rev.ignore_merges = 1; rev.limited = 1; if (suffixcmp(out->buf, "\n")) strbuf_addch(out, '\n'); for (i = 0; i < origins.nr; i++) shortlog(origins.items[i].string, origins.items[i].util, head, &rev, opts->shortlog_len, out); } strbuf_complete_line(out); free(current_branch_to_free); return 0; }
static int checkout_branch(struct checkout_opts *opts, struct branch_info *new_branch_info) { if (opts->pathspec.nr) die(_("paths cannot be used with switching branches")); if (opts->patch_mode) die(_("'%s' cannot be used with switching branches"), "--patch"); if (!opts->overlay_mode) die(_("'%s' cannot be used with switching branches"), "--no-overlay"); if (opts->writeout_stage) die(_("'%s' cannot be used with switching branches"), "--ours/--theirs"); if (opts->force && opts->merge) die(_("'%s' cannot be used with '%s'"), "-f", "-m"); if (opts->force_detach && opts->new_branch) die(_("'%s' cannot be used with '%s'"), "--detach", "-b/-B/--orphan"); if (opts->new_orphan_branch) { if (opts->track != BRANCH_TRACK_UNSPECIFIED) die(_("'%s' cannot be used with '%s'"), "--orphan", "-t"); } else if (opts->force_detach) { if (opts->track != BRANCH_TRACK_UNSPECIFIED) die(_("'%s' cannot be used with '%s'"), "--detach", "-t"); } else if (opts->track == BRANCH_TRACK_UNSPECIFIED) opts->track = git_branch_track; if (new_branch_info->name && !new_branch_info->commit) die(_("Cannot switch branch to a non-commit '%s'"), new_branch_info->name); if (new_branch_info->path && !opts->force_detach && !opts->new_branch && !opts->ignore_other_worktrees) { int flag; char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag); if (head_ref && (!(flag & REF_ISSYMREF) || strcmp(head_ref, new_branch_info->path))) die_if_checked_out(new_branch_info->path, 1); free(head_ref); } if (!new_branch_info->commit && opts->new_branch) { struct object_id rev; int flag; if (!read_ref_full("HEAD", 0, &rev, &flag) && (flag & REF_ISSYMREF) && is_null_oid(&rev)) return switch_unborn_to_new_branch(opts); } return switch_branches(opts, new_branch_info); }
static void execute_commands(struct command *commands, const char *unpacker_error, struct shallow_info *si) { int checked_connectivity; struct command *cmd; unsigned char sha1[20]; struct iterate_data data; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "unpacker error"; return; } data.cmds = commands; data.si = si; if (check_everything_connected(iterate_receive_command_list, 0, &data)) set_connectivity_errors(commands, si); reject_updates_to_hidden(commands); if (run_receive_hook(commands, "pre-receive", 0)) { for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) cmd->error_string = "pre-receive hook declined"; } return; } check_aliased_updates(commands); free(head_name_to_free); head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL); checked_connectivity = 1; for (cmd = commands; cmd; cmd = cmd->next) { if (cmd->error_string) continue; if (cmd->skip_update) continue; cmd->error_string = update(cmd, si); if (shallow_update && !cmd->error_string && si->shallow_ref[cmd->index]) { error("BUG: connectivity check has not been run on ref %s", cmd->ref_name); checked_connectivity = 0; } } if (shallow_update && !checked_connectivity) error("BUG: run 'git fsck' for safety.\n" "If there are errors, try to remove " "the reported refs above"); }
static int merge_commit(struct notes_merge_options *o) { struct strbuf msg = STRBUF_INIT; unsigned char sha1[20], parent_sha1[20]; struct notes_tree *t; struct commit *partial; struct pretty_print_context pretty_ctx; void *local_ref_to_free; int ret; /* * Read partial merge result from .git/NOTES_MERGE_PARTIAL, * and target notes ref from .git/NOTES_MERGE_REF. */ if (get_sha1("NOTES_MERGE_PARTIAL", sha1)) die("Failed to read ref NOTES_MERGE_PARTIAL"); else if (!(partial = lookup_commit_reference(sha1))) die("Could not find commit from NOTES_MERGE_PARTIAL."); else if (parse_commit(partial)) die("Could not parse commit from NOTES_MERGE_PARTIAL."); if (partial->parents) hashcpy(parent_sha1, partial->parents->item->object.sha1); else hashclr(parent_sha1); t = xcalloc(1, sizeof(struct notes_tree)); init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0); o->local_ref = local_ref_to_free = resolve_refdup("NOTES_MERGE_REF", 0, sha1, NULL); if (!o->local_ref) die("Failed to resolve NOTES_MERGE_REF"); if (notes_merge_commit(o, t, partial, sha1)) die("Failed to finalize notes merge"); /* Reuse existing commit message in reflog message */ memset(&pretty_ctx, 0, sizeof(pretty_ctx)); format_commit_message(partial, "%s", &msg, &pretty_ctx); strbuf_trim(&msg); strbuf_insert(&msg, 0, "notes: ", 7); update_ref(msg.buf, o->local_ref, sha1, is_null_sha1(parent_sha1) ? NULL : parent_sha1, 0, UPDATE_REFS_DIE_ON_ERR); free_notes(t); strbuf_release(&msg); ret = merge_abort(o); free(local_ref_to_free); return ret; }
static int switch_branches(const struct checkout_opts *opts, struct branch_info *new_branch_info) { int ret = 0; struct branch_info old_branch_info; void *path_to_free; struct object_id rev; int flag, writeout_error = 0; trace2_cmd_mode("branch"); memset(&old_branch_info, 0, sizeof(old_branch_info)); old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag); if (old_branch_info.path) old_branch_info.commit = lookup_commit_reference_gently(the_repository, &rev, 1); if (!(flag & REF_ISSYMREF)) old_branch_info.path = NULL; if (old_branch_info.path) skip_prefix(old_branch_info.path, "refs/heads/", &old_branch_info.name); if (!new_branch_info->name) { new_branch_info->name = "HEAD"; new_branch_info->commit = old_branch_info.commit; if (!new_branch_info->commit) die(_("You are on a branch yet to be born")); parse_commit_or_die(new_branch_info->commit); } /* optimize the "checkout -b <new_branch> path */ if (skip_merge_working_tree(opts, &old_branch_info, new_branch_info)) { if (!checkout_optimize_new_branch && !opts->quiet) { if (read_cache_preload(NULL) < 0) return error(_("index file corrupt")); show_local_changes(&new_branch_info->commit->object, &opts->diff_options); } } else { ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error); if (ret) { free(path_to_free); return ret; } } if (!opts->quiet && !old_branch_info.path && old_branch_info.commit && new_branch_info->commit != old_branch_info.commit) orphaned_commit_warning(old_branch_info.commit, new_branch_info->commit); update_refs_for_switch(opts, &old_branch_info, new_branch_info); ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1); free(path_to_free); return ret || writeout_error; }
static int branch_merged(int kind, const char *name, struct commit *rev, struct commit *head_rev) { /* * This checks whether the merge bases of branch and HEAD (or * the other branch this branch builds upon) contains the * branch, which means that the branch has already been merged * safely to HEAD (or the other branch). */ struct commit *reference_rev = NULL; const char *reference_name = NULL; void *reference_name_to_free = NULL; int merged; if (kind == REF_LOCAL_BRANCH) { struct branch *branch = branch_get(name); unsigned char sha1[20]; if (branch && branch->merge && branch->merge[0] && branch->merge[0]->dst && (reference_name = reference_name_to_free = resolve_refdup(branch->merge[0]->dst, RESOLVE_REF_READING, sha1, NULL)) != NULL) reference_rev = lookup_commit_reference(sha1); } if (!reference_rev) reference_rev = head_rev; merged = in_merge_bases(rev, reference_rev); /* * After the safety valve is fully redefined to "check with * upstream, if any, otherwise with HEAD", we should just * return the result of the in_merge_bases() above without * any of the following code, but during the transition period, * a gentle reminder is in order. */ if ((head_rev != reference_rev) && in_merge_bases(rev, head_rev) != merged) { if (merged) warning(_("deleting branch '%s' that has been merged to\n" " '%s', but not yet merged to HEAD."), name, reference_name); else warning(_("not deleting branch '%s' that is not yet merged to\n" " '%s', even though it is merged to HEAD."), name, reference_name); } free(reference_name_to_free); return merged; }
void transport_print_push_status(const char *dest, struct ref *refs, int verbose, int porcelain, unsigned int *reject_reasons) { struct ref *ref; int n = 0; char *head; int summary_width = transport_summary_width(refs); if (transport_color_config() < 0) warning(_("could not parse transport.color.* config")); head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL); if (verbose) { for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_UPTODATE) n += print_one_push_status(ref, dest, n, porcelain, summary_width); } for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain, summary_width); *reject_reasons = 0; for (ref = refs; ref; ref = ref->next) { if (ref->status != REF_STATUS_NONE && ref->status != REF_STATUS_UPTODATE && ref->status != REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain, summary_width); if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) { if (head != NULL && !strcmp(head, ref->name)) *reject_reasons |= REJECT_NON_FF_HEAD; else *reject_reasons |= REJECT_NON_FF_OTHER; } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) { *reject_reasons |= REJECT_ALREADY_EXISTS; } else if (ref->status == REF_STATUS_REJECT_FETCH_FIRST) { *reject_reasons |= REJECT_FETCH_FIRST; } else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) { *reject_reasons |= REJECT_NEEDS_FORCE; } } free(head); }
void wt_status_prepare(struct wt_status *s) { unsigned char sha1[20]; memset(s, 0, sizeof(*s)); memcpy(s->color_palette, default_wt_status_colors, sizeof(default_wt_status_colors)); s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; s->use_color = -1; s->relative_paths = 1; s->branch = resolve_refdup("HEAD", sha1, 0, NULL); s->reference = "HEAD"; s->fp = stdout; s->index_file = get_index_file(); s->change.strdup_strings = 1; s->untracked.strdup_strings = 1; s->ignored.strdup_strings = 1; }
static void execute_commands(struct command *commands, const char *unpacker_error, struct shallow_info *si) { struct command *cmd; unsigned char sha1[20]; struct iterate_data data; if (unpacker_error) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "unpacker error"; return; } data.cmds = commands; data.si = si; if (check_everything_connected(iterate_receive_command_list, 0, &data)) set_connectivity_errors(commands, si); reject_updates_to_hidden(commands); if (run_receive_hook(commands, "pre-receive", 0)) { for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) cmd->error_string = "pre-receive hook declined"; } return; } check_aliased_updates(commands); free(head_name_to_free); head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL); if (use_atomic) execute_commands_atomic(commands, si); else execute_commands_non_atomic(commands, si); if (shallow_update) warn_if_skipped_connectivity_check(commands, si); }
static int switch_branches(const struct checkout_opts *opts, struct branch_info *new_branch_info) { int ret = 0; struct branch_info old_branch_info; void *path_to_free; struct object_id rev; int flag, writeout_error = 0; memset(&old_branch_info, 0, sizeof(old_branch_info)); old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag); if (old_branch_info.path) old_branch_info.commit = lookup_commit_reference_gently(&rev, 1); if (!(flag & REF_ISSYMREF)) old_branch_info.path = NULL; if (old_branch_info.path) skip_prefix(old_branch_info.path, "refs/heads/", &old_branch_info.name); if (!new_branch_info->name) { new_branch_info->name = "HEAD"; new_branch_info->commit = old_branch_info.commit; if (!new_branch_info->commit) die(_("You are on a branch yet to be born")); parse_commit_or_die(new_branch_info->commit); } ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error); if (ret) { free(path_to_free); return ret; } if (!opts->quiet && !old_branch_info.path && old_branch_info.commit && new_branch_info->commit != old_branch_info.commit) orphaned_commit_warning(old_branch_info.commit, new_branch_info->commit); update_refs_for_switch(opts, &old_branch_info, new_branch_info); ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1); free(path_to_free); return ret || writeout_error; }
void transport_print_push_status(const char *dest, struct ref *refs, int verbose, int porcelain, unsigned int *reject_reasons) { struct ref *ref; int n = 0; unsigned char head_sha1[20]; char *head; head = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL); if (verbose) { for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_UPTODATE) n += print_one_push_status(ref, dest, n, porcelain); } for (ref = refs; ref; ref = ref->next) if (ref->status == REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain); *reject_reasons = 0; for (ref = refs; ref; ref = ref->next) { if (ref->status != REF_STATUS_NONE && ref->status != REF_STATUS_UPTODATE && ref->status != REF_STATUS_OK) n += print_one_push_status(ref, dest, n, porcelain); if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD) { if (head != NULL && !strcmp(head, ref->name)) *reject_reasons |= REJECT_NON_FF_HEAD; else *reject_reasons |= REJECT_NON_FF_OTHER; } else if (ref->status == REF_STATUS_REJECT_ALREADY_EXISTS) { *reject_reasons |= REJECT_ALREADY_EXISTS; } else if (ref->status == REF_STATUS_REJECT_FETCH_FIRST) { *reject_reasons |= REJECT_FETCH_FIRST; } else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) { *reject_reasons |= REJECT_NEEDS_FORCE; } } free(head); }
int cmd_merge(int argc, const char **argv, const char *prefix) { unsigned char result_tree[20]; unsigned char stash[20]; unsigned char head_sha1[20]; struct commit *head_commit; struct strbuf buf = STRBUF_INIT; const char *head_arg; int flag, i, ret = 0, head_subsumed; int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0; struct commit_list *common = NULL; const char *best_strategy = NULL, *wt_strategy = NULL; struct commit_list *remoteheads, *p; void *branch_to_free; if (argc == 2 && !strcmp(argv[1], "-h")) usage_with_options(builtin_merge_usage, builtin_merge_options); /* * Check if we are _not_ on a detached HEAD, i.e. if there is a * current branch. */ branch = branch_to_free = resolve_refdup("HEAD", head_sha1, 0, &flag); if (branch && !prefixcmp(branch, "refs/heads/")) branch += 11; if (!branch || is_null_sha1(head_sha1)) head_commit = NULL; else head_commit = lookup_commit_or_die(head_sha1, "HEAD"); git_config(git_merge_config, NULL); if (branch_mergeoptions) parse_branch_merge_options(branch_mergeoptions); argc = parse_options(argc, argv, prefix, builtin_merge_options, builtin_merge_usage, 0); if (shortlog_len < 0) shortlog_len = (merge_log_config > 0) ? merge_log_config : 0; if (verbosity < 0 && show_progress == -1) show_progress = 0; if (abort_current_merge) { int nargc = 2; const char *nargv[] = {"reset", "--merge", NULL}; if (!file_exists(git_path("MERGE_HEAD"))) die(_("There is no merge to abort (MERGE_HEAD missing).")); /* Invoke 'git reset --merge' */ ret = cmd_reset(nargc, nargv, prefix); goto done; } if (read_cache_unmerged()) die_resolve_conflict("merge"); if (file_exists(git_path("MERGE_HEAD"))) { /* * There is no unmerged entry, don't advise 'git * add/rm <file>', just 'git commit'. */ if (advice_resolve_conflict) die(_("You have not concluded your merge (MERGE_HEAD exists).\n" "Please, commit your changes before you can merge.")); else die(_("You have not concluded your merge (MERGE_HEAD exists).")); } if (file_exists(git_path("CHERRY_PICK_HEAD"))) { if (advice_resolve_conflict) die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" "Please, commit your changes before you can merge.")); else die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).")); } resolve_undo_clear(); if (verbosity < 0) show_diffstat = 0; if (squash) { if (!allow_fast_forward) die(_("You cannot combine --squash with --no-ff.")); option_commit = 0; } if (!allow_fast_forward && fast_forward_only) die(_("You cannot combine --no-ff with --ff-only.")); if (!abort_current_merge) { if (!argc) { if (default_to_upstream) argc = setup_with_upstream(&argv); else die(_("No commit specified and merge.defaultToUpstream not set.")); } else if (argc == 1 && !strcmp(argv[0], "-")) argv[0] = "@{-1}"; } if (!argc) usage_with_options(builtin_merge_usage, builtin_merge_options); /* * This could be traditional "merge <msg> HEAD <commit>..." and * the way we can tell it is to see if the second token is HEAD, * but some people might have misused the interface and used a * committish that is the same as HEAD there instead. * Traditional format never would have "-m" so it is an * additional safety measure to check for it. */ if (!have_message && head_commit && is_old_style_invocation(argc, argv, head_commit->object.sha1)) { strbuf_addstr(&merge_msg, argv[0]); head_arg = argv[1]; argv += 2; argc -= 2; remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv); } else if (!head_commit) { struct commit *remote_head; /* * If the merged head is a valid one there is no reason * to forbid "git merge" into a branch yet to be born. * We do the same for "git pull". */ if (argc != 1) die(_("Can merge only exactly one commit into " "empty head")); if (squash) die(_("Squash commit into empty head not supported yet")); if (!allow_fast_forward) die(_("Non-fast-forward commit does not make sense into " "an empty head")); remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv); remote_head = remoteheads->item; if (!remote_head) die(_("%s - not something we can merge"), argv[0]); read_empty(remote_head->object.sha1, 0); update_ref("initial pull", "HEAD", remote_head->object.sha1, NULL, 0, DIE_ON_ERR); goto done; } else { struct strbuf merge_names = STRBUF_INIT; /* We are invoked directly as the first-class UI. */ head_arg = "HEAD"; /* * All the rest are the commits being merged; prepare * the standard merge summary message to be appended * to the given message. */ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv); for (p = remoteheads; p; p = p->next) merge_name(merge_remote_util(p->item)->name, &merge_names); if (!have_message || shortlog_len) { struct fmt_merge_msg_opts opts; memset(&opts, 0, sizeof(opts)); opts.add_title = !have_message; opts.shortlog_len = shortlog_len; fmt_merge_msg(&merge_names, &merge_msg, &opts); if (merge_msg.len) strbuf_setlen(&merge_msg, merge_msg.len - 1); } } if (!head_commit || !argc) usage_with_options(builtin_merge_usage, builtin_merge_options); strbuf_addstr(&buf, "merge"); for (p = remoteheads; p; p = p->next) strbuf_addf(&buf, " %s", merge_remote_util(p->item)->name); setenv("GIT_REFLOG_ACTION", buf.buf, 0); strbuf_reset(&buf); for (p = remoteheads; p; p = p->next) { struct commit *commit = p->item; strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(commit->object.sha1)); setenv(buf.buf, merge_remote_util(commit)->name, 1); strbuf_reset(&buf); if (!fast_forward_only && merge_remote_util(commit) && merge_remote_util(commit)->obj && merge_remote_util(commit)->obj->type == OBJ_TAG) allow_fast_forward = 0; } if (option_edit < 0) option_edit = default_edit_option(); if (!use_strategies) { if (!remoteheads) ; /* already up-to-date */ else if (!remoteheads->next) add_strategies(pull_twohead, DEFAULT_TWOHEAD); else add_strategies(pull_octopus, DEFAULT_OCTOPUS); } for (i = 0; i < use_strategies_nr; i++) { if (use_strategies[i]->attr & NO_FAST_FORWARD) allow_fast_forward = 0; if (use_strategies[i]->attr & NO_TRIVIAL) allow_trivial = 0; } if (!remoteheads) ; /* already up-to-date */ else if (!remoteheads->next) common = get_merge_bases(head_commit, remoteheads->item, 1); else { struct commit_list *list = remoteheads; commit_list_insert(head_commit, &list); common = get_octopus_merge_bases(list); free(list); } update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1, NULL, 0, DIE_ON_ERR); if (remoteheads && !common) ; /* No common ancestors found. We need a real merge. */ else if (!remoteheads || (!remoteheads->next && !common->next && common->item == remoteheads->item)) { /* * If head can reach all the merge then we are up to date. * but first the most common case of merging one remote. */ finish_up_to_date("Already up-to-date."); goto done; } else if (allow_fast_forward && !remoteheads->next && !common->next && !hashcmp(common->item->object.sha1, head_commit->object.sha1)) { /* Again the most common case of merging one remote. */ struct strbuf msg = STRBUF_INIT; struct commit *commit; char hex[41]; strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV)); if (verbosity >= 0) printf(_("Updating %s..%s\n"), hex, find_unique_abbrev(remoteheads->item->object.sha1, DEFAULT_ABBREV)); strbuf_addstr(&msg, "Fast-forward"); if (have_message) strbuf_addstr(&msg, " (no commit created; -m option ignored)"); commit = remoteheads->item; if (!commit) { ret = 1; goto done; } if (checkout_fast_forward(head_commit->object.sha1, commit->object.sha1, overwrite_ignore)) { ret = 1; goto done; } finish(head_commit, remoteheads, commit->object.sha1, msg.buf); drop_save(); goto done; } else if (!remoteheads->next && common->next) ; /* * We are not doing octopus and not fast-forward. Need * a real merge. */ else if (!remoteheads->next && !common->next && option_commit) { /* * We are not doing octopus, not fast-forward, and have * only one common. */ refresh_cache(REFRESH_QUIET); if (allow_trivial && !fast_forward_only) { /* See if it is really trivial. */ git_committer_info(IDENT_STRICT); printf(_("Trying really trivial in-index merge...\n")); if (!read_tree_trivial(common->item->object.sha1, head_commit->object.sha1, remoteheads->item->object.sha1)) { ret = merge_trivial(head_commit, remoteheads); goto done; } printf(_("Nope.\n")); } } else { /* * An octopus. If we can reach all the remote we are up * to date. */ int up_to_date = 1; struct commit_list *j; for (j = remoteheads; j; j = j->next) { struct commit_list *common_one; /* * Here we *have* to calculate the individual * merge_bases again, otherwise "git merge HEAD^ * HEAD^^" would be missed. */ common_one = get_merge_bases(head_commit, j->item, 1); if (hashcmp(common_one->item->object.sha1, j->item->object.sha1)) { up_to_date = 0; break; } } if (up_to_date) { finish_up_to_date("Already up-to-date. Yeeah!"); goto done; } } if (fast_forward_only) die(_("Not possible to fast-forward, aborting.")); /* We are going to make a new commit. */ git_committer_info(IDENT_STRICT); /* * At this point, we need a real merge. No matter what strategy * we use, it would operate on the index, possibly affecting the * working tree, and when resolved cleanly, have the desired * tree in the index -- this means that the index must be in * sync with the head commit. The strategies are responsible * to ensure this. */ if (use_strategies_nr == 1 || /* * Stash away the local changes so that we can try more than one. */ save_state(stash)) hashcpy(stash, null_sha1); for (i = 0; i < use_strategies_nr; i++) { int ret; if (i) { printf(_("Rewinding the tree to pristine...\n")); restore_state(head_commit->object.sha1, stash); } if (use_strategies_nr != 1) printf(_("Trying merge strategy %s...\n"), use_strategies[i]->name); /* * Remember which strategy left the state in the working * tree. */ wt_strategy = use_strategies[i]->name; ret = try_merge_strategy(use_strategies[i]->name, common, remoteheads, head_commit, head_arg); if (!option_commit && !ret) { merge_was_ok = 1; /* * This is necessary here just to avoid writing * the tree, but later we will *not* exit with * status code 1 because merge_was_ok is set. */ ret = 1; } if (ret) { /* * The backend exits with 1 when conflicts are * left to be resolved, with 2 when it does not * handle the given merge at all. */ if (ret == 1) { int cnt = evaluate_result(); if (best_cnt <= 0 || cnt <= best_cnt) { best_strategy = use_strategies[i]->name; best_cnt = cnt; } } if (merge_was_ok) break; else continue; } /* Automerge succeeded. */ write_tree_trivial(result_tree); automerge_was_ok = 1; break; } /* * If we have a resulting tree, that means the strategy module * auto resolved the merge cleanly. */ if (automerge_was_ok) { ret = finish_automerge(head_commit, head_subsumed, common, remoteheads, result_tree, wt_strategy); goto done; } /* * Pick the result from the best strategy and have the user fix * it up. */ if (!best_strategy) { restore_state(head_commit->object.sha1, stash); if (use_strategies_nr > 1) fprintf(stderr, _("No merge strategy handled the merge.\n")); else fprintf(stderr, _("Merge with strategy %s failed.\n"), use_strategies[0]->name); ret = 2; goto done; } else if (best_strategy == wt_strategy) ; /* We already have its result in the working tree. */ else { printf(_("Rewinding the tree to pristine...\n")); restore_state(head_commit->object.sha1, stash); printf(_("Using the %s to prepare resolving by hand.\n"), best_strategy); try_merge_strategy(best_strategy, common, remoteheads, head_commit, head_arg); } if (squash) finish(head_commit, remoteheads, NULL, NULL); else write_merge_state(remoteheads); if (merge_was_ok) fprintf(stderr, _("Automatic merge went well; " "stopped before committing as requested\n")); else ret = suggest_conflicts(option_renormalize); done: free(branch_to_free); return ret; }
int add_reflog_for_walk(struct reflog_walk_info *info, struct commit *commit, const char *name) { timestamp_t timestamp = 0; int recno = -1; struct string_list_item *item; struct complete_reflogs *reflogs; char *branch, *at = strchr(name, '@'); struct commit_reflog *commit_reflog; enum selector_type selector = SELECTOR_NONE; if (commit->object.flags & UNINTERESTING) die ("Cannot walk reflogs for %s", name); branch = xstrdup(name); if (at && at[1] == '{') { char *ep; branch[at - name] = '\0'; recno = strtoul(at + 2, &ep, 10); if (*ep != '}') { recno = -1; timestamp = approxidate(at + 2); selector = SELECTOR_DATE; } else selector = SELECTOR_INDEX; } else recno = 0; item = string_list_lookup(&info->complete_reflogs, branch); if (item) reflogs = item->util; else { if (*branch == '\0') { struct object_id oid; free(branch); branch = resolve_refdup("HEAD", 0, oid.hash, NULL); if (!branch) die ("No current branch"); } reflogs = read_complete_reflog(branch); if (!reflogs || reflogs->nr == 0) { struct object_id oid; char *b; int ret = dwim_log(branch, strlen(branch), oid.hash, &b); if (ret > 1) free(b); else if (ret == 1) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(branch); branch = b; reflogs = read_complete_reflog(branch); } } if (!reflogs || reflogs->nr == 0) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(branch); return -1; } string_list_insert(&info->complete_reflogs, branch)->util = reflogs; } free(branch); commit_reflog = xcalloc(1, sizeof(struct commit_reflog)); if (recno < 0) { commit_reflog->recno = get_reflog_recno_by_time(reflogs, timestamp); if (commit_reflog->recno < 0) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(commit_reflog); return -1; } } else commit_reflog->recno = reflogs->nr - recno - 1; commit_reflog->selector = selector; commit_reflog->reflogs = reflogs; add_commit_info(commit, commit_reflog, &info->reflogs); return 0; }
static int checkout(int submodule_progress) { unsigned char sha1[20]; char *head; struct lock_file *lock_file; struct unpack_trees_options opts; struct tree *tree; struct tree_desc t; int err = 0; if (option_no_checkout) return 0; head = resolve_refdup("HEAD", RESOLVE_REF_READING, sha1, NULL); if (!head) { warning(_("remote HEAD refers to nonexistent ref, " "unable to checkout.\n")); return 0; } if (!strcmp(head, "HEAD")) { if (advice_detached_head) detach_advice(sha1_to_hex(sha1)); } else { if (!starts_with(head, "refs/heads/")) die(_("HEAD not found below refs/heads!")); } free(head); /* We need to be in the new work tree for the checkout */ setup_work_tree(); lock_file = xcalloc(1, sizeof(struct lock_file)); hold_locked_index(lock_file, LOCK_DIE_ON_ERROR); memset(&opts, 0, sizeof opts); opts.update = 1; opts.merge = 1; opts.fn = oneway_merge; opts.verbose_update = (option_verbosity >= 0); opts.src_index = &the_index; opts.dst_index = &the_index; tree = parse_tree_indirect(sha1); parse_tree(tree); init_tree_desc(&t, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts) < 0) die(_("unable to checkout working tree")); if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1), sha1_to_hex(sha1), "1", NULL); if (!err && option_recursive) { struct argv_array args = ARGV_ARRAY_INIT; argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); if (option_shallow_submodules == 1) argv_array_push(&args, "--depth=1"); if (max_jobs != -1) argv_array_pushf(&args, "--jobs=%d", max_jobs); if (submodule_progress) argv_array_push(&args, "--progress"); err = run_command_v_opt(args.argv, RUN_GIT_CMD); argv_array_clear(&args); } return err; }
int cmd_show_branch(int ac, const char **av, const char *prefix) { struct commit *rev[MAX_REVS], *commit; char *reflog_msg[MAX_REVS]; struct commit_list *list = NULL, *seen = NULL; unsigned int rev_mask[MAX_REVS]; int num_rev, i, extra = 0; int all_heads = 0, all_remotes = 0; int all_mask, all_revs; enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER; char head[128]; const char *head_p; int head_len; struct object_id head_oid; int merge_base = 0; int independent = 0; int no_name = 0; int sha1_name = 0; int shown_merge_point = 0; int with_current_branch = 0; int head_at = -1; int topics = 0; int dense = 1; const char *reflog_base = NULL; struct option builtin_show_branch_options[] = { OPT_BOOL('a', "all", &all_heads, N_("show remote-tracking and local branches")), OPT_BOOL('r', "remotes", &all_remotes, N_("show remote-tracking branches")), OPT__COLOR(&showbranch_use_color, N_("color '*!+-' corresponding to the branch")), { OPTION_INTEGER, 0, "more", &extra, N_("n"), N_("show <n> more commits after the common ancestor"), PARSE_OPT_OPTARG, NULL, (intptr_t)1 }, OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1), OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")), OPT_BOOL(0, "current", &with_current_branch, N_("include the current branch")), OPT_BOOL(0, "sha1-name", &sha1_name, N_("name commits with their object names")), OPT_BOOL(0, "merge-base", &merge_base, N_("show possible merge bases")), OPT_BOOL(0, "independent", &independent, N_("show refs unreachable from any other ref")), OPT_SET_INT(0, "topo-order", &sort_order, N_("show commits in topological order"), REV_SORT_IN_GRAPH_ORDER), OPT_BOOL(0, "topics", &topics, N_("show only commits not on the first branch")), OPT_SET_INT(0, "sparse", &dense, N_("show merges reachable from only one tip"), 0), OPT_SET_INT(0, "date-order", &sort_order, N_("topologically sort, maintaining date order " "where possible"), REV_SORT_BY_COMMIT_DATE), { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"), N_("show <n> most recent ref-log entries starting at " "base"), PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parse_reflog_param }, OPT_END() }; git_config(git_show_branch_config, NULL); /* If nothing is specified, try the default first */ if (ac == 1 && default_num) { ac = default_num; av = default_arg; } ac = parse_options(ac, av, prefix, builtin_show_branch_options, show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (all_heads) all_remotes = 1; if (extra || reflog) { /* "listing" mode is incompatible with * independent nor merge-base modes. */ if (independent || merge_base) usage_with_options(show_branch_usage, builtin_show_branch_options); if (reflog && ((0 < extra) || all_heads || all_remotes)) /* * Asking for --more in reflog mode does not * make sense. --list is Ok. * * Also --all and --remotes do not make sense either. */ die("--reflog is incompatible with --all, --remotes, " "--independent or --merge-base"); } /* If nothing is specified, show all branches by default */ if (ac <= topics && all_heads + all_remotes == 0) all_heads = 1; if (reflog) { struct object_id oid; char nth_desc[256]; char *ref; int base = 0; unsigned int flags = 0; if (ac == 0) { static const char *fake_av[2]; fake_av[0] = resolve_refdup("HEAD", RESOLVE_REF_READING, oid.hash, NULL); fake_av[1] = NULL; av = fake_av; ac = 1; } if (ac != 1) die("--reflog option needs one branch name"); if (MAX_REVS < reflog) die("Only %d entries can be shown at one time.", MAX_REVS); if (!dwim_ref(*av, strlen(*av), oid.hash, &ref)) die("No such ref %s", *av); /* Has the base been specified? */ if (reflog_base) { char *ep; base = strtoul(reflog_base, &ep, 10); if (*ep) { /* Ah, that is a date spec... */ unsigned long at; at = approxidate(reflog_base); read_ref_at(ref, flags, at, -1, oid.hash, NULL, NULL, NULL, &base); } } for (i = 0; i < reflog; i++) { char *logmsg; const char *msg; unsigned long timestamp; int tz; if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg, ×tamp, &tz, NULL)) { reflog = i; break; } msg = strchr(logmsg, '\t'); if (!msg) msg = "(none)"; else msg++; reflog_msg[i] = xstrfmt("(%s) %s", show_date(timestamp, tz, 1), msg); free(logmsg); sprintf(nth_desc, "%s@{%d}", *av, base+i); append_ref(nth_desc, &oid, 1); } free(ref); } else { while (0 < ac) { append_one_rev(*av); ac--; av++; } if (all_heads + all_remotes) snarf_refs(all_heads, all_remotes); } head_p = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_oid.hash, NULL); if (head_p) { head_len = strlen(head_p); memcpy(head, head_p, head_len + 1); } else { head_len = 0; head[0] = 0; } if (with_current_branch && head_p) { int has_head = 0; for (i = 0; !has_head && i < ref_name_cnt; i++) { /* We are only interested in adding the branch * HEAD points at. */ if (rev_is_head(head, head_len, ref_name[i], head_oid.hash, NULL)) has_head++; } if (!has_head) { int offset = starts_with(head, "refs/heads/") ? 11 : 0; append_one_rev(head + offset); } } if (!ref_name_cnt) { fprintf(stderr, "No revs to be shown.\n"); exit(0); } for (num_rev = 0; ref_name[num_rev]; num_rev++) { struct object_id revkey; unsigned int flag = 1u << (num_rev + REV_SHIFT); if (MAX_REVS <= num_rev) die("cannot handle more than %d revs.", MAX_REVS); if (get_sha1(ref_name[num_rev], revkey.hash)) die("'%s' is not a valid ref.", ref_name[num_rev]); commit = lookup_commit_reference(revkey.hash); if (!commit) die("cannot find commit %s (%s)", ref_name[num_rev], oid_to_hex(&revkey)); parse_commit(commit); mark_seen(commit, &seen); /* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1, * and so on. REV_SHIFT bits from bit 0 are used for * internal bookkeeping. */ commit->object.flags |= flag; if (commit->object.flags == flag) commit_list_insert_by_date(commit, &list); rev[num_rev] = commit; } for (i = 0; i < num_rev; i++) rev_mask[i] = rev[i]->object.flags; if (0 <= extra) join_revs(&list, &seen, num_rev, extra); commit_list_sort_by_date(&seen); if (merge_base) return show_merge_base(seen, num_rev); if (independent) return show_independent(rev, num_rev, ref_name, rev_mask); /* Show list; --more=-1 means list-only */ if (1 < num_rev || extra < 0) { for (i = 0; i < num_rev; i++) { int j; int is_head = rev_is_head(head, head_len, ref_name[i], head_oid.hash, rev[i]->object.sha1); if (extra < 0) printf("%c [%s] ", is_head ? '*' : ' ', ref_name[i]); else { for (j = 0; j < i; j++) putchar(' '); printf("%s%c%s [%s] ", get_color_code(i), is_head ? '*' : '!', get_color_reset_code(), ref_name[i]); } if (!reflog) { /* header lines never need name */ show_one_commit(rev[i], 1); } else puts(reflog_msg[i]); if (is_head) head_at = i; } if (0 <= extra) { for (i = 0; i < num_rev; i++) putchar('-'); putchar('\n'); } } if (extra < 0) exit(0); /* Sort topologically */ sort_in_topological_order(&seen, sort_order); /* Give names to commits */ if (!sha1_name && !no_name) name_commits(seen, rev, ref_name, num_rev); all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); while (seen) { struct commit *commit = pop_one_commit(&seen); int this_flag = commit->object.flags; int is_merge_point = ((this_flag & all_revs) == all_revs); shown_merge_point |= is_merge_point; if (1 < num_rev) { int is_merge = !!(commit->parents && commit->parents->next); if (topics && !is_merge_point && (this_flag & (1u << REV_SHIFT))) continue; if (dense && is_merge && omit_in_dense(commit, rev, num_rev)) continue; for (i = 0; i < num_rev; i++) { int mark; if (!(this_flag & (1u << (i + REV_SHIFT)))) mark = ' '; else if (is_merge) mark = '-'; else if (i == head_at) mark = '*'; else mark = '+'; printf("%s%c%s", get_color_code(i), mark, get_color_reset_code()); } putchar(' '); } show_one_commit(commit, no_name); if (shown_merge_point && --extra < 0) break; } return 0; }
static int delete_branches(int argc, const char **argv, int force, int kinds, int quiet) { struct commit *head_rev = NULL; unsigned char sha1[20]; char *name = NULL; const char *fmt; int i; int ret = 0; int remote_branch = 0; struct strbuf bname = STRBUF_INIT; switch (kinds) { case FILTER_REFS_REMOTES: fmt = "refs/remotes/%s"; /* For subsequent UI messages */ remote_branch = 1; force = 1; break; case FILTER_REFS_BRANCHES: fmt = "refs/heads/%s"; break; default: die(_("cannot use -a with -d")); } if (!force) { head_rev = lookup_commit_reference(head_sha1); if (!head_rev) die(_("Couldn't look up commit object for HEAD")); } for (i = 0; i < argc; i++, strbuf_release(&bname)) { char *target = NULL; int flags = 0; strbuf_branchname(&bname, argv[i]); free(name); name = mkpathdup(fmt, bname.buf); if (kinds == FILTER_REFS_BRANCHES) { const struct worktree *wt = find_shared_symref("HEAD", name); if (wt) { error(_("Cannot delete branch '%s' " "checked out at '%s'"), bname.buf, wt->path); ret = 1; continue; } } target = resolve_refdup(name, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE | RESOLVE_REF_ALLOW_BAD_NAME, sha1, &flags); if (!target) { error(remote_branch ? _("remote-tracking branch '%s' not found.") : _("branch '%s' not found."), bname.buf); ret = 1; continue; } if (!(flags & (REF_ISSYMREF|REF_ISBROKEN)) && check_branch_commit(bname.buf, name, sha1, head_rev, kinds, force)) { ret = 1; goto next; } if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1, REF_NODEREF)) { error(remote_branch ? _("Error deleting remote-tracking branch '%s'") : _("Error deleting branch '%s'"), bname.buf); ret = 1; goto next; } if (!quiet) { printf(remote_branch ? _("Deleted remote-tracking branch %s (was %s).\n") : _("Deleted branch %s (was %s).\n"), bname.buf, (flags & REF_ISBROKEN) ? "broken" : (flags & REF_ISSYMREF) ? target : find_unique_abbrev(sha1, DEFAULT_ABBREV)); } delete_branch_config(bname.buf); next: free(target); } free(name); return(ret); }
int fmt_merge_msg(struct strbuf *in, struct strbuf *out, struct fmt_merge_msg_opts *opts) { int i = 0, pos = 0; unsigned char head_sha1[20]; const char *current_branch; void *current_branch_to_free; struct merge_parents merge_parents; memset(&merge_parents, 0, sizeof(merge_parents)); /* get current branch */ current_branch = current_branch_to_free = resolve_refdup("HEAD", RESOLVE_REF_READING, head_sha1, NULL); if (!current_branch) die("No current branch"); if (starts_with(current_branch, "refs/heads/")) current_branch += 11; find_merge_parents(&merge_parents, in, head_sha1); /* get a line */ while (pos < in->len) { int len; char *newline, *p = in->buf + pos; newline = strchr(p, '\n'); len = newline ? newline - p : strlen(p); pos += len + !!newline; i++; p[len] = 0; if (handle_line(p, &merge_parents)) die ("Error in line %d: %.*s", i, len, p); } if (opts->add_title && srcs.nr) fmt_merge_msg_title(out, current_branch); if (origins.nr) fmt_merge_msg_sigs(out); if (opts->shortlog_len) { struct commit *head; struct rev_info rev; head = lookup_commit_or_die(head_sha1, "HEAD"); init_revisions(&rev, NULL); rev.commit_format = CMIT_FMT_ONELINE; rev.merge_diff_mode = MERGE_DIFF_IGNORE; rev.limited = 1; strbuf_complete_line(out); for (i = 0; i < origins.nr; i++) shortlog(origins.items[i].string, origins.items[i].util, head, &rev, opts, out); } strbuf_complete_line(out); free(current_branch_to_free); free(merge_parents.item); return 0; }