int cmd_reset(int argc, const char **argv, const char *prefix) { int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0; int patch_mode = 0; const char *rev = "HEAD"; unsigned char sha1[20], *orig = NULL, sha1_orig[20], *old_orig = NULL, sha1_old_orig[20]; struct commit *commit; struct strbuf msg = STRBUF_INIT; const struct option options[] = { OPT__QUIET(&quiet, "be quiet, only report errors"), OPT_SET_INT(0, "mixed", &reset_type, "reset HEAD and index", MIXED), OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT), OPT_SET_INT(0, "hard", &reset_type, "reset HEAD, index and working tree", HARD), OPT_SET_INT(0, "merge", &reset_type, "reset HEAD, index and working tree", MERGE), OPT_SET_INT(0, "keep", &reset_type, "reset HEAD but keep local changes", KEEP), OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"), OPT_END() }; git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_reset_usage, PARSE_OPT_KEEP_DASHDASH); /* * Possible arguments are: * * git reset [-opts] <rev> <paths>... * git reset [-opts] <rev> -- <paths>... * git reset [-opts] -- <paths>... * git reset [-opts] <paths>... * * At this point, argv[i] points immediately after [-opts]. */ if (i < argc) { if (!strcmp(argv[i], "--")) { i++; /* reset to HEAD, possibly with paths */ } else if (i + 1 < argc && !strcmp(argv[i+1], "--")) { rev = argv[i]; i += 2; } /* * Otherwise, argv[i] could be either <rev> or <paths> and * has to be unambiguous. */ else if (!get_sha1(argv[i], sha1)) { /* * Ok, argv[i] looks like a rev; it should not * be a filename. */ verify_non_filename(prefix, argv[i]); rev = argv[i++]; } else { /* Otherwise we treat this as a filename */ verify_filename(prefix, argv[i]); } } if (get_sha1(rev, sha1)) die(_("Failed to resolve '%s' as a valid ref."), rev); commit = lookup_commit_reference(sha1); if (!commit) die(_("Could not parse object '%s'."), rev); hashcpy(sha1, commit->object.sha1); if (patch_mode) { if (reset_type != NONE) die(_("--patch is incompatible with --{hard,mixed,soft}")); return interactive_reset(rev, argv + i, prefix); } /* git reset tree [--] paths... can be used to * load chosen paths from the tree into the index without * affecting the working tree nor HEAD. */ if (i < argc) { if (reset_type == MIXED) warning(_("--mixed with paths is deprecated; use 'git reset -- <paths>' instead.")); else if (reset_type != NONE) die(_("Cannot do %s reset with paths."), _(reset_type_names[reset_type])); return read_from_tree(prefix, argv + i, sha1, quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN); } if (reset_type == NONE) reset_type = MIXED; /* by default */ if (reset_type != SOFT && reset_type != MIXED) setup_work_tree(); if (reset_type == MIXED && is_bare_repository()) die(_("%s reset is not allowed in a bare repository"), _(reset_type_names[reset_type])); /* Soft reset does not touch the index file nor the working tree * at all, but requires them in a good order. Other resets reset * the index file to the tree object we are switching to. */ if (reset_type == SOFT) die_if_unmerged_cache(reset_type); else { int err; if (reset_type == KEEP) die_if_unmerged_cache(reset_type); err = reset_index_file(sha1, reset_type, quiet); if (reset_type == KEEP) err = err || reset_index_file(sha1, MIXED, quiet); if (err) die(_("Could not reset index file to revision '%s'."), rev); } /* Any resets update HEAD to the head being switched to, * saving the previous head in ORIG_HEAD before. */ if (!get_sha1("ORIG_HEAD", sha1_old_orig)) old_orig = sha1_old_orig; if (!get_sha1("HEAD", sha1_orig)) { orig = sha1_orig; set_reflog_message(&msg, "updating ORIG_HEAD", NULL); update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR); } else if (old_orig) delete_ref("ORIG_HEAD", old_orig, 0); set_reflog_message(&msg, "updating HEAD", rev); update_ref_status = update_ref(msg.buf, "HEAD", sha1, orig, 0, MSG_ON_ERR); switch (reset_type) { case HARD: if (!update_ref_status && !quiet) print_new_head_line(commit); break; case SOFT: /* Nothing else to do. */ break; case MIXED: /* Report what has not been updated. */ update_index_refresh(0, NULL, quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN); break; } remove_branch_state(); strbuf_release(&msg); return update_ref_status; }
static void update_refs_for_switch(const struct checkout_opts *opts, struct branch_info *old_branch_info, struct branch_info *new_branch_info) { struct strbuf msg = STRBUF_INIT; const char *old_desc, *reflog_msg; if (opts->new_branch) { if (opts->new_orphan_branch) { char *refname; refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch); if (opts->new_branch_log && !should_autocreate_reflog(refname)) { int ret; struct strbuf err = STRBUF_INIT; ret = safe_create_reflog(refname, 1, &err); if (ret) { fprintf(stderr, _("Can not do reflog for '%s': %s\n"), opts->new_orphan_branch, err.buf); strbuf_release(&err); free(refname); return; } strbuf_release(&err); } free(refname); } else create_branch(opts->new_branch, new_branch_info->name, opts->new_branch_force ? 1 : 0, opts->new_branch_force ? 1 : 0, opts->new_branch_log, opts->quiet, opts->track); new_branch_info->name = opts->new_branch; setup_branch_path(new_branch_info); } old_desc = old_branch_info->name; if (!old_desc && old_branch_info->commit) old_desc = oid_to_hex(&old_branch_info->commit->object.oid); reflog_msg = getenv("GIT_REFLOG_ACTION"); if (!reflog_msg) strbuf_addf(&msg, "checkout: moving from %s to %s", old_desc ? old_desc : "(invalid)", new_branch_info->name); else strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg)); if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) { /* Nothing to do. */ } else if (opts->force_detach || !new_branch_info->path) { /* No longer on any branch. */ update_ref(msg.buf, "HEAD", &new_branch_info->commit->object.oid, NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR); if (!opts->quiet) { if (old_branch_info->path && advice_detached_head && !opts->force_detach) detach_advice(new_branch_info->name); describe_detached_head(_("HEAD is now at"), new_branch_info->commit); } } else if (new_branch_info->path) { /* Switch branches. */ if (create_symref("HEAD", new_branch_info->path, msg.buf) < 0) die(_("unable to update HEAD")); if (!opts->quiet) { if (old_branch_info->path && !strcmp(new_branch_info->path, old_branch_info->path)) { if (opts->new_branch_force) fprintf(stderr, _("Reset branch '%s'\n"), new_branch_info->name); else fprintf(stderr, _("Already on '%s'\n"), new_branch_info->name); } else if (opts->new_branch) { if (opts->branch_exists) fprintf(stderr, _("Switched to and reset branch '%s'\n"), new_branch_info->name); else fprintf(stderr, _("Switched to a new branch '%s'\n"), new_branch_info->name); } else { fprintf(stderr, _("Switched to branch '%s'\n"), new_branch_info->name); } } if (old_branch_info->path && old_branch_info->name) { if (!ref_exists(old_branch_info->path) && reflog_exists(old_branch_info->path)) delete_reflog(old_branch_info->path); } } remove_branch_state(); strbuf_release(&msg); if (!opts->quiet && (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD")))) report_tracking(new_branch_info); }
static int merge(int argc, const char **argv, const char *prefix) { struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT; struct object_id result_oid; struct notes_tree *t; struct notes_merge_options o; int do_merge = 0, do_commit = 0, do_abort = 0; int verbosity = 0, result; const char *strategy = NULL; struct option options[] = { OPT_GROUP(N_("General options")), OPT__VERBOSITY(&verbosity), OPT_GROUP(N_("Merge options")), OPT_STRING('s', "strategy", &strategy, N_("strategy"), N_("resolve notes conflicts using the given strategy " "(manual/ours/theirs/union/cat_sort_uniq)")), OPT_GROUP(N_("Committing unmerged notes")), { OPTION_SET_INT, 0, "commit", &do_commit, NULL, N_("finalize notes merge by committing unmerged notes"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1}, OPT_GROUP(N_("Aborting notes merge resolution")), { OPTION_SET_INT, 0, "abort", &do_abort, NULL, N_("abort notes merge"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1}, OPT_END() }; argc = parse_options(argc, argv, prefix, options, git_notes_merge_usage, 0); if (strategy || do_commit + do_abort == 0) do_merge = 1; if (do_merge + do_commit + do_abort != 1) { error(_("cannot mix --commit, --abort or -s/--strategy")); usage_with_options(git_notes_merge_usage, options); } if (do_merge && argc != 1) { error(_("must specify a notes ref to merge")); usage_with_options(git_notes_merge_usage, options); } else if (!do_merge && argc) { error(_("too many parameters")); usage_with_options(git_notes_merge_usage, options); } init_notes_merge_options(&o); o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT; if (do_abort) return merge_abort(&o); if (do_commit) return merge_commit(&o); o.local_ref = default_notes_ref(); strbuf_addstr(&remote_ref, argv[0]); expand_loose_notes_ref(&remote_ref); o.remote_ref = remote_ref.buf; t = init_notes_check("merge", NOTES_INIT_WRITABLE); if (strategy) { if (parse_notes_merge_strategy(strategy, &o.strategy)) { error(_("unknown -s/--strategy: %s"), strategy); usage_with_options(git_notes_merge_usage, options); } } else { struct strbuf merge_key = STRBUF_INIT; const char *short_ref = NULL; if (!skip_prefix(o.local_ref, "refs/notes/", &short_ref)) die("BUG: local ref %s is outside of refs/notes/", o.local_ref); strbuf_addf(&merge_key, "notes.%s.mergeStrategy", short_ref); if (git_config_get_notes_strategy(merge_key.buf, &o.strategy)) git_config_get_notes_strategy("notes.mergeStrategy", &o.strategy); strbuf_release(&merge_key); } strbuf_addf(&msg, "notes: Merged notes from %s into %s", remote_ref.buf, default_notes_ref()); strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */ result = notes_merge(&o, t, &result_oid); if (result >= 0) /* Merge resulted (trivially) in result_oid */ /* Update default notes ref with new commit */ update_ref(msg.buf, default_notes_ref(), result_oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ const struct worktree *wt; /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); if (wt) die(_("a notes merge into %s is already in-progress at %s"), default_notes_ref(), wt->path); if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) die(_("failed to store link to current notes ref (%s)"), default_notes_ref()); printf(_("Automatic notes merge failed. Fix conflicts in %s and " "commit the result with 'git notes merge --commit', or " "abort the merge with 'git notes merge --abort'.\n"), git_path(NOTES_MERGE_WORKTREE)); } free_notes(t); strbuf_release(&remote_ref); strbuf_release(&msg); return result < 0; /* return non-zero on conflicts */ }
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 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", 0, head_sha1, NULL); if (branch && starts_with(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"); init_diff_ui_defaults(); 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 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 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 (fast_forward == FF_NO) die(_("You cannot combine --squash with --no-ff.")); option_commit = 0; } 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); if (!head_commit) { /* * 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". */ unsigned char *remote_head_sha1; if (squash) die(_("Squash commit into empty head not supported yet")); if (fast_forward == FF_NO) die(_("Non-fast-forward commit does not make sense into " "an empty head")); remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv, NULL); if (!remoteheads) die(_("%s - not something we can merge"), argv[0]); if (remoteheads->next) die(_("Can merge only exactly one commit into empty head")); remote_head_sha1 = remoteheads->item->object.oid.hash; read_empty(remote_head_sha1, 0); update_ref("initial pull", "HEAD", remote_head_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); goto done; } /* * 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 * commit-ish 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, head_commit->object.oid.hash)) { warning("old-style 'git merge <msg> HEAD <commit>' is deprecated."); strbuf_addstr(&merge_msg, argv[0]); head_arg = argv[1]; argv += 2; argc -= 2; remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv, NULL); } else { /* 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, &merge_msg); } if (!head_commit || !argc) usage_with_options(builtin_merge_usage, builtin_merge_options); if (verify_signatures) { for (p = remoteheads; p; p = p->next) { struct commit *commit = p->item; char hex[GIT_SHA1_HEXSZ + 1]; struct signature_check signature_check; memset(&signature_check, 0, sizeof(signature_check)); check_commit_signature(commit, &signature_check); find_unique_abbrev_r(hex, commit->object.oid.hash, DEFAULT_ABBREV); switch (signature_check.result) { case 'G': break; case 'U': die(_("Commit %s has an untrusted GPG signature, " "allegedly by %s."), hex, signature_check.signer); case 'B': die(_("Commit %s has a bad GPG signature " "allegedly by %s."), hex, signature_check.signer); default: /* 'N' */ die(_("Commit %s does not have a GPG signature."), hex); } if (verbosity >= 0 && signature_check.result == 'G') printf(_("Commit %s has a good GPG signature by %s\n"), hex, signature_check.signer); signature_check_clear(&signature_check); } } 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", oid_to_hex(&commit->object.oid)); setenv(buf.buf, merge_remote_util(commit)->name, 1); strbuf_reset(&buf); if (fast_forward != FF_ONLY && merge_remote_util(commit) && merge_remote_util(commit)->obj && merge_remote_util(commit)->obj->type == OBJ_TAG) fast_forward = FF_NO; } 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) fast_forward = FF_NO; 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); 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.oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); if (remoteheads && !common) { /* No common ancestors found. */ if (!allow_unrelated_histories) die(_("refusing to merge unrelated histories")); /* otherwise, 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 (fast_forward != FF_NO && !remoteheads->next && !common->next && !oidcmp(&common->item->object.oid, &head_commit->object.oid)) { /* Again the most common case of merging one remote. */ struct strbuf msg = STRBUF_INIT; struct commit *commit; if (verbosity >= 0) { char from[GIT_SHA1_HEXSZ + 1], to[GIT_SHA1_HEXSZ + 1]; find_unique_abbrev_r(from, head_commit->object.oid.hash, DEFAULT_ABBREV); find_unique_abbrev_r(to, remoteheads->item->object.oid.hash, DEFAULT_ABBREV); printf(_("Updating %s..%s\n"), from, to); } 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.oid.hash, commit->object.oid.hash, overwrite_ignore)) { ret = 1; goto done; } finish(head_commit, remoteheads, commit->object.oid.hash, 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 != FF_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.oid.hash, head_commit->object.oid.hash, remoteheads->item->object.oid.hash)) { 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); if (oidcmp(&common_one->item->object.oid, &j->item->object.oid)) { up_to_date = 0; break; } } if (up_to_date) { finish_up_to_date(_("Already up-to-date. Yeeah!")); goto done; } } if (fast_forward == FF_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)) hashclr(stash); for (i = 0; i < use_strategies_nr; i++) { int ret; if (i) { printf(_("Rewinding the tree to pristine...\n")); restore_state(head_commit->object.oid.hash, 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.oid.hash, 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.oid.hash, 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(); done: free(branch_to_free); return ret; }
int cmd_clone(int argc, const char **argv, const char *prefix) { int is_bundle = 0, is_local; struct stat buf; const char *repo_name, *repo, *work_tree, *git_dir; char *path, *dir; int dest_exists; const struct ref *refs, *remote_head; const struct ref *remote_head_points_at; const struct ref *our_head_points_at; struct ref *mapped_refs; struct strbuf key = STRBUF_INIT, value = STRBUF_INIT; struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT; struct transport *transport = NULL; char *src_ref_prefix = "refs/heads/"; int err = 0; struct refspec *refspec; const char *fetch_pattern; junk_pid = getpid(); packet_trace_identity("clone"); argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); if (argc > 2) usage_msg_opt(_("Too many arguments."), builtin_clone_usage, builtin_clone_options); if (argc == 0) usage_msg_opt(_("You must specify a repository to clone."), builtin_clone_usage, builtin_clone_options); if (option_mirror) option_bare = 1; if (option_bare) { if (option_origin) die(_("--bare and --origin %s options are incompatible."), option_origin); option_no_checkout = 1; } if (!option_origin) option_origin = "origin"; repo_name = argv[0]; path = get_repo_path(repo_name, &is_bundle); if (path) repo = xstrdup(absolute_path(repo_name)); else if (!strchr(repo_name, ':')) die(_("repository '%s' does not exist"), repo_name); else repo = repo_name; is_local = path && !is_bundle; if (is_local && option_depth) warning(_("--depth is ignored in local clones; use file:// instead.")); if (argc == 2) dir = xstrdup(argv[1]); else dir = guess_dir_name(repo_name, is_bundle, option_bare); strip_trailing_slashes(dir); dest_exists = !stat(dir, &buf); if (dest_exists && !is_empty_dir(dir)) die(_("destination path '%s' already exists and is not " "an empty directory."), dir); strbuf_addf(&reflog_msg, "clone: from %s", repo); if (option_bare) work_tree = NULL; else { work_tree = getenv("GIT_WORK_TREE"); if (work_tree && !stat(work_tree, &buf)) die(_("working tree '%s' already exists."), work_tree); } if (option_bare || work_tree) git_dir = xstrdup(dir); else { work_tree = dir; git_dir = xstrdup(mkpath("%s/.git", dir)); } if (!option_bare) { junk_work_tree = work_tree; if (safe_create_leading_directories_const(work_tree) < 0) die_errno(_("could not create leading directories of '%s'"), work_tree); if (!dest_exists && mkdir(work_tree, 0755)) die_errno(_("could not create work tree dir '%s'."), work_tree); set_git_work_tree(work_tree); } junk_git_dir = git_dir; atexit(remove_junk); sigchain_push_common(remove_junk_on_signal); setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1); if (safe_create_leading_directories_const(git_dir) < 0) die(_("could not create leading directories of '%s'"), git_dir); set_git_dir_init(git_dir, real_git_dir, 0); if (real_git_dir) git_dir = real_git_dir; if (0 <= option_verbosity) { if (option_bare) printf(_("Cloning into bare repository %s...\n"), dir); else printf(_("Cloning into %s...\n"), dir); } init_db(option_template, INIT_DB_QUIET); /* * At this point, the config exists, so we do not need the * environment variable. We actually need to unset it, too, to * re-enable parsing of the global configs. */ unsetenv(CONFIG_ENVIRONMENT); git_config(git_default_config, NULL); if (option_bare) { if (option_mirror) src_ref_prefix = "refs/"; strbuf_addstr(&branch_top, src_ref_prefix); git_config_set("core.bare", "true"); } else { strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin); } strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf); if (option_mirror || !option_bare) { /* Configure the remote */ strbuf_addf(&key, "remote.%s.fetch", option_origin); git_config_set_multivar(key.buf, value.buf, "^$", 0); strbuf_reset(&key); if (option_mirror) { strbuf_addf(&key, "remote.%s.mirror", option_origin); git_config_set(key.buf, "true"); strbuf_reset(&key); } } strbuf_addf(&key, "remote.%s.url", option_origin); git_config_set(key.buf, repo); strbuf_reset(&key); if (option_reference) setup_reference(git_dir); fetch_pattern = value.buf; refspec = parse_fetch_refspec(1, &fetch_pattern); strbuf_reset(&value); if (is_local) { refs = clone_local(path, git_dir); mapped_refs = wanted_peer_refs(refs, refspec); } else { struct remote *remote = remote_get(option_origin); transport = transport_get(remote, remote->url[0]); if (!transport->get_refs_list || !transport->fetch) die(_("Don't know how to clone %s"), transport->url); transport_set_option(transport, TRANS_OPT_KEEP, "yes"); if (option_depth) transport_set_option(transport, TRANS_OPT_DEPTH, option_depth); transport_set_verbosity(transport, option_verbosity, option_progress); if (option_upload_pack) transport_set_option(transport, TRANS_OPT_UPLOADPACK, option_upload_pack); refs = transport_get_remote_refs(transport); if (refs) { mapped_refs = wanted_peer_refs(refs, refspec); transport_fetch_refs(transport, mapped_refs); } } if (refs) { clear_extra_refs(); write_remote_refs(mapped_refs); remote_head = find_ref_by_name(refs, "HEAD"); remote_head_points_at = guess_remote_head(remote_head, mapped_refs, 0); if (option_branch) { struct strbuf head = STRBUF_INIT; strbuf_addstr(&head, src_ref_prefix); strbuf_addstr(&head, option_branch); our_head_points_at = find_ref_by_name(mapped_refs, head.buf); strbuf_release(&head); if (!our_head_points_at) { warning(_("Remote branch %s not found in " "upstream %s, using HEAD instead"), option_branch, option_origin); our_head_points_at = remote_head_points_at; } } else our_head_points_at = remote_head_points_at; } else { warning(_("You appear to have cloned an empty repository.")); our_head_points_at = NULL; remote_head_points_at = NULL; remote_head = NULL; option_no_checkout = 1; if (!option_bare) install_branch_config(0, "master", option_origin, "refs/heads/master"); } if (remote_head_points_at && !option_bare) { struct strbuf head_ref = STRBUF_INIT; strbuf_addstr(&head_ref, branch_top.buf); strbuf_addstr(&head_ref, "HEAD"); create_symref(head_ref.buf, remote_head_points_at->peer_ref->name, reflog_msg.buf); } if (our_head_points_at) { /* Local default branch link */ create_symref("HEAD", our_head_points_at->name, NULL); if (!option_bare) { const char *head = skip_prefix(our_head_points_at->name, "refs/heads/"); update_ref(reflog_msg.buf, "HEAD", our_head_points_at->old_sha1, NULL, 0, DIE_ON_ERR); install_branch_config(0, head, option_origin, our_head_points_at->name); } } else if (remote_head) { /* Source had detached HEAD pointing somewhere. */ if (!option_bare) { update_ref(reflog_msg.buf, "HEAD", remote_head->old_sha1, NULL, REF_NODEREF, DIE_ON_ERR); our_head_points_at = remote_head; } } else { /* Nothing to checkout out */ if (!option_no_checkout) warning(_("remote HEAD refers to nonexistent ref, " "unable to checkout.\n")); option_no_checkout = 1; } if (transport) { transport_unlock_pack(transport); transport_disconnect(transport); } if (!option_no_checkout) { struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); struct unpack_trees_options opts; struct tree *tree; struct tree_desc t; int fd; /* We need to be in the new work tree for the checkout */ setup_work_tree(); 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(our_head_points_at->old_sha1); parse_tree(tree); init_tree_desc(&t, tree->buffer, tree->size); unpack_trees(1, &t, &opts); 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(our_head_points_at->old_sha1), "1", NULL); if (!err && option_recursive) err = run_command_v_opt(argv_submodule, RUN_GIT_CMD); } strbuf_release(&reflog_msg); strbuf_release(&branch_top); strbuf_release(&key); strbuf_release(&value); junk_pid = 0; return err; }
int cmd_clone(int argc, const char **argv, const char *prefix) { int use_local_hardlinks = 1; int use_separate_remote = 1; int is_bundle = 0; struct stat buf; const char *repo_name, *repo, *work_tree, *git_dir; char *path, *dir; const struct ref *refs, *head_points_at, *remote_head, *mapped_refs; char branch_top[256], key[256], value[256]; struct strbuf reflog_msg = STRBUF_INIT; struct transport *transport = NULL; char *src_ref_prefix = "refs/heads/"; struct refspec refspec; junk_pid = getpid(); argc = parse_options(argc, argv, builtin_clone_options, builtin_clone_usage, 0); if (argc == 0) die("You must specify a repository to clone."); if (option_no_hardlinks) use_local_hardlinks = 0; if (option_mirror) option_bare = 1; if (option_bare) { if (option_origin) die("--bare and --origin %s options are incompatible.", option_origin); option_no_checkout = 1; use_separate_remote = 0; } if (!option_origin) option_origin = "origin"; repo_name = argv[0]; path = get_repo_path(repo_name, &is_bundle); if (path) repo = xstrdup(make_nonrelative_path(repo_name)); else if (!strchr(repo_name, ':')) repo = xstrdup(make_absolute_path(repo_name)); else repo = repo_name; if (argc == 2) dir = xstrdup(argv[1]); else dir = guess_dir_name(repo_name, is_bundle, option_bare); strip_trailing_slashes(dir); if (!stat(dir, &buf)) die("destination directory '%s' already exists.", dir); strbuf_addf(&reflog_msg, "clone: from %s", repo); if (option_bare) work_tree = NULL; else { work_tree = getenv("GIT_WORK_TREE"); if (work_tree && !stat(work_tree, &buf)) die("working tree '%s' already exists.", work_tree); } if (option_bare || work_tree) git_dir = xstrdup(dir); else { work_tree = dir; git_dir = xstrdup(mkpath("%s/.git", dir)); } if (!option_bare) { junk_work_tree = work_tree; if (safe_create_leading_directories_const(work_tree) < 0) die("could not create leading directories of '%s': %s", work_tree, strerror(errno)); if (mkdir(work_tree, 0755)) die("could not create work tree dir '%s': %s.", work_tree, strerror(errno)); set_git_work_tree(work_tree); } junk_git_dir = git_dir; atexit(remove_junk); signal(SIGINT, remove_junk_on_signal); setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); if (safe_create_leading_directories_const(git_dir) < 0) die("could not create leading directories of '%s'", git_dir); set_git_dir(make_absolute_path(git_dir)); init_db(option_template, option_quiet ? INIT_DB_QUIET : 0); /* * At this point, the config exists, so we do not need the * environment variable. We actually need to unset it, too, to * re-enable parsing of the global configs. */ unsetenv(CONFIG_ENVIRONMENT); if (option_reference) setup_reference(git_dir); git_config(git_default_config, NULL); if (option_bare) { if (option_mirror) src_ref_prefix = "refs/"; strcpy(branch_top, src_ref_prefix); git_config_set("core.bare", "true"); } else { snprintf(branch_top, sizeof(branch_top), "refs/remotes/%s/", option_origin); } if (option_mirror || !option_bare) { /* Configure the remote */ if (option_mirror) { snprintf(key, sizeof(key), "remote.%s.mirror", option_origin); git_config_set(key, "true"); } snprintf(key, sizeof(key), "remote.%s.url", option_origin); git_config_set(key, repo); snprintf(key, sizeof(key), "remote.%s.fetch", option_origin); snprintf(value, sizeof(value), "+%s*:%s*", src_ref_prefix, branch_top); git_config_set_multivar(key, value, "^$", 0); } refspec.force = 0; refspec.pattern = 1; refspec.src = src_ref_prefix; refspec.dst = branch_top; if (path && !is_bundle) refs = clone_local(path, git_dir); else { struct remote *remote = remote_get(argv[0]); transport = transport_get(remote, remote->url[0]); if (!transport->get_refs_list || !transport->fetch) die("Don't know how to clone %s", transport->url); transport_set_option(transport, TRANS_OPT_KEEP, "yes"); if (option_depth) transport_set_option(transport, TRANS_OPT_DEPTH, option_depth); if (option_quiet) transport->verbose = -1; else if (option_verbose) transport->progress = 1; if (option_upload_pack) transport_set_option(transport, TRANS_OPT_UPLOADPACK, option_upload_pack); refs = transport_get_remote_refs(transport); transport_fetch_refs(transport, refs); } clear_extra_refs(); mapped_refs = write_remote_refs(refs, &refspec, reflog_msg.buf); head_points_at = locate_head(refs, mapped_refs, &remote_head); if (head_points_at) { /* Local default branch link */ create_symref("HEAD", head_points_at->name, NULL); if (!option_bare) { struct strbuf head_ref = STRBUF_INIT; const char *head = head_points_at->name; if (!prefixcmp(head, "refs/heads/")) head += 11; /* Set up the initial local branch */ /* Local branch initial value */ update_ref(reflog_msg.buf, "HEAD", head_points_at->old_sha1, NULL, 0, DIE_ON_ERR); strbuf_addstr(&head_ref, branch_top); strbuf_addstr(&head_ref, "HEAD"); /* Remote branch link */ create_symref(head_ref.buf, head_points_at->peer_ref->name, reflog_msg.buf); snprintf(key, sizeof(key), "branch.%s.remote", head); git_config_set(key, option_origin); snprintf(key, sizeof(key), "branch.%s.merge", head); git_config_set(key, head_points_at->name); } } else if (remote_head) { /* Source had detached HEAD pointing somewhere. */ if (!option_bare) update_ref(reflog_msg.buf, "HEAD", remote_head->old_sha1, NULL, REF_NODEREF, DIE_ON_ERR); } else { /* Nothing to checkout out */ if (!option_no_checkout) warning("remote HEAD refers to nonexistent ref, " "unable to checkout.\n"); option_no_checkout = 1; } if (transport) transport_unlock_pack(transport); if (!option_no_checkout) { struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); struct unpack_trees_options opts; struct tree *tree; struct tree_desc t; int fd; /* We need to be in the new work tree for the checkout */ setup_work_tree(); 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_quiet; opts.src_index = &the_index; opts.dst_index = &the_index; tree = parse_tree_indirect(remote_head->old_sha1); parse_tree(tree); init_tree_desc(&t, tree->buffer, tree->size); unpack_trees(1, &t, &opts); if (write_cache(fd, active_cache, active_nr) || commit_locked_index(lock_file)) die("unable to write new index file"); } strbuf_release(&reflog_msg); junk_pid = 0; return 0; }