static void write_merge_state(void) { const char *filename; int fd; struct commit_list *j; struct strbuf buf = STRBUF_INIT; for (j = remoteheads; j; j = j->next) strbuf_addf(&buf, "%s\n", sha1_to_hex(j->item->object.sha1)); filename = git_path("MERGE_HEAD"); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); strbuf_addch(&merge_msg, '\n'); write_merge_msg(&merge_msg); filename = git_path("MERGE_MODE"); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); strbuf_reset(&buf); if (!allow_fast_forward) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); }
static void run_prepare_commit_msg(void) { write_merge_msg(); run_hook(get_index_file(), "prepare-commit-msg", git_path("MERGE_MSG"), "merge", NULL, NULL); read_merge_msg(); }
int git_revert( git_repository *repo, git_commit *commit, const git_revert_options *given_opts) { git_revert_options opts; git_reference *our_ref = NULL; git_commit *our_commit = NULL; char commit_oidstr[GIT_OID_HEXSZ + 1]; const char *commit_msg; git_buf their_label = GIT_BUF_INIT; git_index *index = NULL; git_indexwriter indexwriter = GIT_INDEXWRITER_INIT; int error; assert(repo && commit); GITERR_CHECK_VERSION(given_opts, GIT_REVERT_OPTIONS_VERSION, "git_revert_options"); if ((error = git_repository__ensure_not_bare(repo, "revert")) < 0) return error; git_oid_fmt(commit_oidstr, git_commit_id(commit)); commit_oidstr[GIT_OID_HEXSZ] = '\0'; if ((commit_msg = git_commit_summary(commit)) == NULL) { error = -1; goto on_error; } if ((error = git_buf_printf(&their_label, "parent of %.7s... %s", commit_oidstr, commit_msg)) < 0 || (error = revert_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 || (error = git_indexwriter_init_for_operation(&indexwriter, repo, &opts.checkout_opts.checkout_strategy)) < 0 || (error = write_revert_head(repo, commit_oidstr)) < 0 || (error = write_merge_msg(repo, commit_oidstr, commit_msg)) < 0 || (error = git_repository_head(&our_ref, repo)) < 0 || (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_revert_commit(&index, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 || (error = git_merge__check_result(repo, index)) < 0 || (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0 || (error = git_checkout_index(repo, index, &opts.checkout_opts)) < 0 || (error = git_indexwriter_commit(&indexwriter)) < 0) goto on_error; goto done; on_error: revert_state_cleanup(repo); done: git_indexwriter_cleanup(&indexwriter); git_index_free(index); git_commit_free(our_commit); git_reference_free(our_ref); git_buf_free(&their_label); return error; }
int git_cherry_pick( git_repository *repo, git_commit *commit, const git_cherry_pick_options *given_opts) { git_cherry_pick_options opts; git_reference *our_ref = NULL; git_commit *our_commit = NULL; char commit_oidstr[GIT_OID_HEXSZ + 1]; const char *commit_msg, *commit_summary; git_buf their_label = GIT_BUF_INIT; git_index *index_new = NULL; int error = 0; assert(repo && commit); GITERR_CHECK_VERSION(given_opts, GIT_CHERRY_PICK_OPTIONS_VERSION, "git_cherry_pick_options"); if ((error = git_repository__ensure_not_bare(repo, "cherry-pick")) < 0) return error; if ((commit_msg = git_commit_message(commit)) == NULL || (commit_summary = git_commit_summary(commit)) == NULL) { error = -1; goto on_error; } git_oid_nfmt(commit_oidstr, sizeof(commit_oidstr), git_commit_id(commit)); if ((error = write_merge_msg(repo, commit_msg)) < 0 || (error = git_buf_printf(&their_label, "%.7s... %s", commit_oidstr, commit_summary)) < 0 || (error = cherry_pick_normalize_opts(repo, &opts, given_opts, git_buf_cstr(&their_label))) < 0 || (error = write_cherry_pick_head(repo, commit_oidstr)) < 0 || (error = git_repository_head(&our_ref, repo)) < 0 || (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_cherry_pick_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 || (error = git_merge__check_result(repo, index_new)) < 0 || (error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 || (error = git_checkout_index(repo, index_new, &opts.checkout_opts)) < 0) goto on_error; goto done; on_error: cherry_pick_state_cleanup(repo); done: git_index_free(index_new); git_commit_free(our_commit); git_reference_free(our_ref); git_buf_free(&their_label); return error; }
static void prepare_to_commit(void) { struct strbuf msg = STRBUF_INIT; strbuf_addbuf(&msg, &merge_msg); strbuf_addch(&msg, '\n'); write_merge_msg(&msg); run_hook(get_index_file(), "prepare-commit-msg", git_path("MERGE_MSG"), "merge", NULL, NULL); if (option_edit) { if (launch_editor(git_path("MERGE_MSG"), NULL, NULL)) abort_commit(NULL); } read_merge_msg(&msg); stripspace(&msg, option_edit); if (!msg.len) abort_commit(_("Empty commit message.")); strbuf_release(&merge_msg); strbuf_addbuf(&merge_msg, &msg); strbuf_release(&msg); }
static void write_merge_state(struct commit_list *remoteheads) { const char *filename; int fd; struct commit_list *j; struct strbuf buf = STRBUF_INIT; for (j = remoteheads; j; j = j->next) { unsigned const char *sha1; struct commit *c = j->item; if (c->util && merge_remote_util(c)->obj) { sha1 = merge_remote_util(c)->obj->sha1; } else { sha1 = c->object.sha1; } strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1)); } filename = git_path("MERGE_HEAD"); fd = open(filename, O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); strbuf_addch(&merge_msg, '\n'); write_merge_msg(&merge_msg); filename = git_path("MERGE_MODE"); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), filename); strbuf_reset(&buf); if (fast_forward == FF_NO) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), filename); close(fd); }
static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; strbuf_addbuf(&msg, &merge_msg); strbuf_addch(&msg, '\n'); if (0 < option_edit) strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char); write_merge_msg(&msg); if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", git_path("MERGE_MSG"), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { if (launch_editor(git_path("MERGE_MSG"), NULL, NULL)) abort_commit(remoteheads, NULL); } read_merge_msg(&msg); stripspace(&msg, 0 < option_edit); if (!msg.len) abort_commit(remoteheads, _("Empty commit message.")); strbuf_release(&merge_msg); strbuf_addbuf(&merge_msg, &msg); strbuf_release(&msg); }
int cmd_merge(int argc, const char **argv, const char *prefix) { unsigned char result_tree[20]; struct strbuf buf = STRBUF_INIT; const char *head_arg; int flag, head_invalid = 0, i; 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 **remotes = &remoteheads; 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 = resolve_ref("HEAD", head, 0, &flag); if (branch && !prefixcmp(branch, "refs/heads/")) branch += 11; if (is_null_sha1(head)) head_invalid = 1; git_config(git_merge_config, NULL); /* for color.ui */ if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; if (branch_mergeoptions) parse_branch_merge_options(branch_mergeoptions); argc = parse_options(argc, argv, prefix, builtin_merge_options, builtin_merge_usage, 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' */ return cmd_reset(nargc, nargv, prefix); } 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 (!argc && !abort_current_merge && default_to_upstream) argc = setup_with_upstream(&argv); 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 && is_old_style_invocation(argc, argv)) { strbuf_addstr(&merge_msg, argv[0]); head_arg = argv[1]; argv += 2; argc -= 2; } else if (head_invalid) { struct object *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")); remote_head = peel_to_type(argv[0], 0, NULL, OBJ_COMMIT); if (!remote_head) die(_("%s - not something we can merge"), argv[0]); read_empty(remote_head->sha1, 0); update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0, DIE_ON_ERR); return 0; } 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. If remote * is invalid we will die later in the common * codepath so we discard the error in this * loop. */ for (i = 0; i < argc; i++) merge_name(argv[i], &merge_names); if (!have_message || shortlog_len) { fmt_merge_msg(&merge_names, &merge_msg, !have_message, shortlog_len); if (merge_msg.len) strbuf_setlen(&merge_msg, merge_msg.len - 1); } } if (head_invalid || !argc) usage_with_options(builtin_merge_usage, builtin_merge_options); strbuf_addstr(&buf, "merge"); for (i = 0; i < argc; i++) strbuf_addf(&buf, " %s", argv[i]); setenv("GIT_REFLOG_ACTION", buf.buf, 0); strbuf_reset(&buf); for (i = 0; i < argc; i++) { struct object *o; struct commit *commit; o = peel_to_type(argv[i], 0, NULL, OBJ_COMMIT); if (!o) die(_("%s - not something we can merge"), argv[i]); commit = lookup_commit(o->sha1); commit->util = (void *)argv[i]; remotes = &commit_list_insert(commit, remotes)->next; strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1)); setenv(buf.buf, argv[i], 1); strbuf_reset(&buf); } if (!use_strategies) { 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->next) common = get_merge_bases(lookup_commit(head), remoteheads->item, 1); else { struct commit_list *list = remoteheads; commit_list_insert(lookup_commit(head), &list); common = get_octopus_merge_bases(list); free(list); } update_ref("updating ORIG_HEAD", "ORIG_HEAD", head, NULL, 0, DIE_ON_ERR); if (!common) ; /* No common ancestors found. We need a real merge. */ else if (!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."); return 0; } else if (allow_fast_forward && !remoteheads->next && !common->next && !hashcmp(common->item->object.sha1, head)) { /* Again the most common case of merging one remote. */ struct strbuf msg = STRBUF_INIT; struct object *o; char hex[41]; strcpy(hex, find_unique_abbrev(head, 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)"); o = peel_to_type(sha1_to_hex(remoteheads->item->object.sha1), 0, NULL, OBJ_COMMIT); if (!o) return 1; if (checkout_fast_forward(head, remoteheads->item->object.sha1)) return 1; finish(o->sha1, msg.buf); drop_save(); return 0; } 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_ERROR_ON_NO_NAME); printf(_("Trying really trivial in-index merge...\n")); if (!read_tree_trivial(common->item->object.sha1, head, remoteheads->item->object.sha1)) return merge_trivial(); 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(lookup_commit(head), 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!"); return 0; } } if (fast_forward_only) die(_("Not possible to fast-forward, aborting.")); /* We are going to make a new commit. */ git_committer_info(IDENT_ERROR_ON_NO_NAME); /* * 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(); } else { memcpy(stash, null_sha1, 20); } for (i = 0; i < use_strategies_nr; i++) { int ret; if (i) { printf(_("Rewinding the tree to pristine...\n")); restore_state(); } 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, 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) return finish_automerge(common, result_tree, wt_strategy); /* * Pick the result from the best strategy and have the user fix * it up. */ if (!best_strategy) { restore_state(); 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); return 2; } 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(); printf(_("Using the %s to prepare resolving by hand.\n"), best_strategy); try_merge_strategy(best_strategy, common, head_arg); } if (squash) finish(NULL, NULL); else { int fd; struct commit_list *j; for (j = remoteheads; j; j = j->next) strbuf_addf(&buf, "%s\n", sha1_to_hex(j->item->object.sha1)); fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), git_path("MERGE_HEAD")); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), git_path("MERGE_HEAD")); close(fd); strbuf_addch(&merge_msg, '\n'); write_merge_msg(); fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) die_errno(_("Could not open '%s' for writing"), git_path("MERGE_MODE")); strbuf_reset(&buf); if (!allow_fast_forward) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) die_errno(_("Could not write to '%s'"), git_path("MERGE_MODE")); close(fd); } if (merge_was_ok) { fprintf(stderr, _("Automatic merge went well; " "stopped before committing as requested\n")); return 0; } else return suggest_conflicts(option_renormalize); }