mirror of
https://github.com/git/git
synced 2024-08-27 03:29:21 +00:00
Merge branch 'nd/maint-autofix-tag-in-head' into next
* nd/maint-autofix-tag-in-head: Accept tags in HEAD or MERGE_HEAD merge: remove global variable head[] merge: use return value of resolve_ref() to determine if HEAD is invalid merge: keep stash[] a local variable Conflicts: builtin/merge.c
This commit is contained in:
commit
c083e6915d
|
@ -1393,7 +1393,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||||
if (get_sha1("HEAD", sha1))
|
if (get_sha1("HEAD", sha1))
|
||||||
current_head = NULL;
|
current_head = NULL;
|
||||||
else {
|
else {
|
||||||
current_head = lookup_commit(sha1);
|
current_head = lookup_commit_or_die(sha1, "HEAD");
|
||||||
if (!current_head || parse_commit(current_head))
|
if (!current_head || parse_commit(current_head))
|
||||||
die(_("could not parse HEAD commit"));
|
die(_("could not parse HEAD commit"));
|
||||||
}
|
}
|
||||||
|
@ -1425,6 +1425,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||||
pptr = &commit_list_insert(c->item, pptr)->next;
|
pptr = &commit_list_insert(c->item, pptr)->next;
|
||||||
} else if (whence == FROM_MERGE) {
|
} else if (whence == FROM_MERGE) {
|
||||||
struct strbuf m = STRBUF_INIT;
|
struct strbuf m = STRBUF_INIT;
|
||||||
|
struct commit *commit;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!reflog_msg)
|
if (!reflog_msg)
|
||||||
|
@ -1438,7 +1439,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
if (get_sha1_hex(m.buf, sha1) < 0)
|
if (get_sha1_hex(m.buf, sha1) < 0)
|
||||||
die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
|
die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
|
||||||
pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
|
commit = lookup_commit_or_die(sha1, "MERGE_HEAD");
|
||||||
|
pptr = &commit_list_insert(commit, pptr)->next;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
strbuf_release(&m);
|
strbuf_release(&m);
|
||||||
|
|
|
@ -293,7 +293,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
|
||||||
struct commit *head;
|
struct commit *head;
|
||||||
struct rev_info rev;
|
struct rev_info rev;
|
||||||
|
|
||||||
head = lookup_commit(head_sha1);
|
head = lookup_commit_or_die(head_sha1, "HEAD");
|
||||||
init_revisions(&rev, NULL);
|
init_revisions(&rev, NULL);
|
||||||
rev.commit_format = CMIT_FMT_ONELINE;
|
rev.commit_format = CMIT_FMT_ONELINE;
|
||||||
rev.ignore_merges = 1;
|
rev.ignore_merges = 1;
|
||||||
|
|
117
builtin/merge.c
117
builtin/merge.c
|
@ -50,7 +50,6 @@ static int fast_forward_only;
|
||||||
static int allow_trivial = 1, have_message;
|
static int allow_trivial = 1, have_message;
|
||||||
static struct strbuf merge_msg;
|
static struct strbuf merge_msg;
|
||||||
static struct commit_list *remoteheads;
|
static struct commit_list *remoteheads;
|
||||||
static unsigned char head[20], stash[20];
|
|
||||||
static struct strategy **use_strategies;
|
static struct strategy **use_strategies;
|
||||||
static size_t use_strategies_nr, use_strategies_alloc;
|
static size_t use_strategies_nr, use_strategies_alloc;
|
||||||
static const char **xopts;
|
static const char **xopts;
|
||||||
|
@ -217,7 +216,7 @@ static void drop_save(void)
|
||||||
unlink(git_path("MERGE_MODE"));
|
unlink(git_path("MERGE_MODE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_state(void)
|
static int save_state(unsigned char *stash)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
struct child_process cp;
|
struct child_process cp;
|
||||||
|
@ -236,11 +235,12 @@ static void save_state(void)
|
||||||
|
|
||||||
if (finish_command(&cp) || len < 0)
|
if (finish_command(&cp) || len < 0)
|
||||||
die(_("stash failed"));
|
die(_("stash failed"));
|
||||||
else if (!len)
|
else if (!len) /* no changes */
|
||||||
return;
|
return -1;
|
||||||
strbuf_setlen(&buffer, buffer.len-1);
|
strbuf_setlen(&buffer, buffer.len-1);
|
||||||
if (get_sha1(buffer.buf, stash))
|
if (get_sha1(buffer.buf, stash))
|
||||||
die(_("not a valid object: %s"), buffer.buf);
|
die(_("not a valid object: %s"), buffer.buf);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_empty(unsigned const char *sha1, int verbose)
|
static void read_empty(unsigned const char *sha1, int verbose)
|
||||||
|
@ -278,7 +278,8 @@ static void reset_hard(unsigned const char *sha1, int verbose)
|
||||||
die(_("read-tree failed"));
|
die(_("read-tree failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_state(void)
|
static void restore_state(const unsigned char *head,
|
||||||
|
const unsigned char *stash)
|
||||||
{
|
{
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
const char *args[] = { "stash", "apply", NULL, NULL };
|
const char *args[] = { "stash", "apply", NULL, NULL };
|
||||||
|
@ -308,10 +309,9 @@ static void finish_up_to_date(const char *msg)
|
||||||
drop_save();
|
drop_save();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void squash_message(void)
|
static void squash_message(struct commit *commit)
|
||||||
{
|
{
|
||||||
struct rev_info rev;
|
struct rev_info rev;
|
||||||
struct commit *commit;
|
|
||||||
struct strbuf out = STRBUF_INIT;
|
struct strbuf out = STRBUF_INIT;
|
||||||
struct commit_list *j;
|
struct commit_list *j;
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -326,7 +326,6 @@ static void squash_message(void)
|
||||||
rev.ignore_merges = 1;
|
rev.ignore_merges = 1;
|
||||||
rev.commit_format = CMIT_FMT_MEDIUM;
|
rev.commit_format = CMIT_FMT_MEDIUM;
|
||||||
|
|
||||||
commit = lookup_commit(head);
|
|
||||||
commit->object.flags |= UNINTERESTING;
|
commit->object.flags |= UNINTERESTING;
|
||||||
add_pending_object(&rev, &commit->object, NULL);
|
add_pending_object(&rev, &commit->object, NULL);
|
||||||
|
|
||||||
|
@ -355,9 +354,11 @@ static void squash_message(void)
|
||||||
strbuf_release(&out);
|
strbuf_release(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finish(const unsigned char *new_head, const char *msg)
|
static void finish(struct commit *head_commit,
|
||||||
|
const unsigned char *new_head, const char *msg)
|
||||||
{
|
{
|
||||||
struct strbuf reflog_message = STRBUF_INIT;
|
struct strbuf reflog_message = STRBUF_INIT;
|
||||||
|
const unsigned char *head = head_commit->object.sha1;
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
|
strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
|
||||||
|
@ -368,7 +369,7 @@ static void finish(const unsigned char *new_head, const char *msg)
|
||||||
getenv("GIT_REFLOG_ACTION"), msg);
|
getenv("GIT_REFLOG_ACTION"), msg);
|
||||||
}
|
}
|
||||||
if (squash) {
|
if (squash) {
|
||||||
squash_message();
|
squash_message(head_commit);
|
||||||
} else {
|
} else {
|
||||||
if (verbosity >= 0 && !merge_msg.len)
|
if (verbosity >= 0 && !merge_msg.len)
|
||||||
printf(_("No merge message -- not updating HEAD\n"));
|
printf(_("No merge message -- not updating HEAD\n"));
|
||||||
|
@ -671,7 +672,7 @@ int try_merge_command(const char *strategy, size_t xopts_nr,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
||||||
const char *head_arg)
|
struct commit *head, const char *head_arg)
|
||||||
{
|
{
|
||||||
int index_fd;
|
int index_fd;
|
||||||
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
|
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
|
||||||
|
@ -717,7 +718,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
|
||||||
commit_list_insert(j->item, &reversed);
|
commit_list_insert(j->item, &reversed);
|
||||||
|
|
||||||
index_fd = hold_locked_index(lock, 1);
|
index_fd = hold_locked_index(lock, 1);
|
||||||
clean = merge_recursive(&o, lookup_commit(head),
|
clean = merge_recursive(&o, head,
|
||||||
remoteheads->item, reversed, &result);
|
remoteheads->item, reversed, &result);
|
||||||
if (active_cache_changed &&
|
if (active_cache_changed &&
|
||||||
(write_cache(index_fd, active_cache, active_nr) ||
|
(write_cache(index_fd, active_cache, active_nr) ||
|
||||||
|
@ -868,25 +869,26 @@ static void run_prepare_commit_msg(void)
|
||||||
read_merge_msg();
|
read_merge_msg();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int merge_trivial(void)
|
static int merge_trivial(struct commit *head)
|
||||||
{
|
{
|
||||||
unsigned char result_tree[20], result_commit[20];
|
unsigned char result_tree[20], result_commit[20];
|
||||||
struct commit_list *parent = xmalloc(sizeof(*parent));
|
struct commit_list *parent = xmalloc(sizeof(*parent));
|
||||||
|
|
||||||
write_tree_trivial(result_tree);
|
write_tree_trivial(result_tree);
|
||||||
printf(_("Wonderful.\n"));
|
printf(_("Wonderful.\n"));
|
||||||
parent->item = lookup_commit(head);
|
parent->item = head;
|
||||||
parent->next = xmalloc(sizeof(*parent->next));
|
parent->next = xmalloc(sizeof(*parent->next));
|
||||||
parent->next->item = remoteheads->item;
|
parent->next->item = remoteheads->item;
|
||||||
parent->next->next = NULL;
|
parent->next->next = NULL;
|
||||||
run_prepare_commit_msg();
|
run_prepare_commit_msg();
|
||||||
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
|
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
|
||||||
finish(result_commit, "In-index merge");
|
finish(head, result_commit, "In-index merge");
|
||||||
drop_save();
|
drop_save();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int finish_automerge(struct commit_list *common,
|
static int finish_automerge(struct commit *head,
|
||||||
|
struct commit_list *common,
|
||||||
unsigned char *result_tree,
|
unsigned char *result_tree,
|
||||||
const char *wt_strategy)
|
const char *wt_strategy)
|
||||||
{
|
{
|
||||||
|
@ -897,12 +899,12 @@ static int finish_automerge(struct commit_list *common,
|
||||||
free_commit_list(common);
|
free_commit_list(common);
|
||||||
if (allow_fast_forward) {
|
if (allow_fast_forward) {
|
||||||
parents = remoteheads;
|
parents = remoteheads;
|
||||||
commit_list_insert(lookup_commit(head), &parents);
|
commit_list_insert(head, &parents);
|
||||||
parents = reduce_heads(parents);
|
parents = reduce_heads(parents);
|
||||||
} else {
|
} else {
|
||||||
struct commit_list **pptr = &parents;
|
struct commit_list **pptr = &parents;
|
||||||
|
|
||||||
pptr = &commit_list_insert(lookup_commit(head),
|
pptr = &commit_list_insert(head,
|
||||||
pptr)->next;
|
pptr)->next;
|
||||||
for (j = remoteheads; j; j = j->next)
|
for (j = remoteheads; j; j = j->next)
|
||||||
pptr = &commit_list_insert(j->item, pptr)->next;
|
pptr = &commit_list_insert(j->item, pptr)->next;
|
||||||
|
@ -912,7 +914,7 @@ static int finish_automerge(struct commit_list *common,
|
||||||
run_prepare_commit_msg();
|
run_prepare_commit_msg();
|
||||||
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
|
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
|
||||||
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
|
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
|
||||||
finish(result_commit, buf.buf);
|
finish(head, result_commit, buf.buf);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
drop_save();
|
drop_save();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -946,7 +948,8 @@ static int suggest_conflicts(int renormalizing)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct commit *is_old_style_invocation(int argc, const char **argv)
|
static struct commit *is_old_style_invocation(int argc, const char **argv,
|
||||||
|
const unsigned char *head)
|
||||||
{
|
{
|
||||||
struct commit *second_token = NULL;
|
struct commit *second_token = NULL;
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
|
@ -1018,9 +1021,12 @@ static int setup_with_upstream(const char ***argv)
|
||||||
int cmd_merge(int argc, const char **argv, const char *prefix)
|
int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
unsigned char result_tree[20];
|
unsigned char result_tree[20];
|
||||||
|
unsigned char stash[20];
|
||||||
|
unsigned char head_sha1[20];
|
||||||
|
struct commit *head_commit;
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
const char *head_arg;
|
const char *head_arg;
|
||||||
int flag, head_invalid = 0, i;
|
int flag, i;
|
||||||
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
|
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
|
||||||
struct commit_list *common = NULL;
|
struct commit_list *common = NULL;
|
||||||
const char *best_strategy = NULL, *wt_strategy = NULL;
|
const char *best_strategy = NULL, *wt_strategy = NULL;
|
||||||
|
@ -1033,11 +1039,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
||||||
* current branch.
|
* current branch.
|
||||||
*/
|
*/
|
||||||
branch = resolve_ref("HEAD", head, 0, &flag);
|
branch = resolve_ref("HEAD", head_sha1, 0, &flag);
|
||||||
if (branch && !prefixcmp(branch, "refs/heads/"))
|
if (branch && !prefixcmp(branch, "refs/heads/"))
|
||||||
branch += 11;
|
branch += 11;
|
||||||
if (is_null_sha1(head))
|
if (!branch || is_null_sha1(head_sha1))
|
||||||
head_invalid = 1;
|
head_commit = NULL;
|
||||||
|
else
|
||||||
|
head_commit = lookup_commit_or_die(head_sha1, "HEAD");
|
||||||
|
|
||||||
git_config(git_merge_config, NULL);
|
git_config(git_merge_config, NULL);
|
||||||
|
|
||||||
|
@ -1114,12 +1122,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
* additional safety measure to check for it.
|
* additional safety measure to check for it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!have_message && is_old_style_invocation(argc, argv)) {
|
if (!have_message && head_commit &&
|
||||||
|
is_old_style_invocation(argc, argv, head_commit->object.sha1)) {
|
||||||
strbuf_addstr(&merge_msg, argv[0]);
|
strbuf_addstr(&merge_msg, argv[0]);
|
||||||
head_arg = argv[1];
|
head_arg = argv[1];
|
||||||
argv += 2;
|
argv += 2;
|
||||||
argc -= 2;
|
argc -= 2;
|
||||||
} else if (head_invalid) {
|
} else if (!head_commit) {
|
||||||
struct object *remote_head;
|
struct object *remote_head;
|
||||||
/*
|
/*
|
||||||
* If the merged head is a valid one there is no reason
|
* If the merged head is a valid one there is no reason
|
||||||
|
@ -1166,7 +1175,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_invalid || !argc)
|
if (!head_commit || !argc)
|
||||||
usage_with_options(builtin_merge_usage,
|
usage_with_options(builtin_merge_usage,
|
||||||
builtin_merge_options);
|
builtin_merge_options);
|
||||||
|
|
||||||
|
@ -1207,17 +1216,16 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!remoteheads->next)
|
if (!remoteheads->next)
|
||||||
common = get_merge_bases(lookup_commit(head),
|
common = get_merge_bases(head_commit, remoteheads->item, 1);
|
||||||
remoteheads->item, 1);
|
|
||||||
else {
|
else {
|
||||||
struct commit_list *list = remoteheads;
|
struct commit_list *list = remoteheads;
|
||||||
commit_list_insert(lookup_commit(head), &list);
|
commit_list_insert(head_commit, &list);
|
||||||
common = get_octopus_merge_bases(list);
|
common = get_octopus_merge_bases(list);
|
||||||
free(list);
|
free(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head, NULL, 0,
|
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
|
||||||
DIE_ON_ERR);
|
NULL, 0, DIE_ON_ERR);
|
||||||
|
|
||||||
if (!common)
|
if (!common)
|
||||||
; /* No common ancestors found. We need a real merge. */
|
; /* No common ancestors found. We need a real merge. */
|
||||||
|
@ -1231,13 +1239,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (allow_fast_forward && !remoteheads->next &&
|
} else if (allow_fast_forward && !remoteheads->next &&
|
||||||
!common->next &&
|
!common->next &&
|
||||||
!hashcmp(common->item->object.sha1, head)) {
|
!hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
|
||||||
/* Again the most common case of merging one remote. */
|
/* Again the most common case of merging one remote. */
|
||||||
struct strbuf msg = STRBUF_INIT;
|
struct strbuf msg = STRBUF_INIT;
|
||||||
struct object *o;
|
struct object *o;
|
||||||
char hex[41];
|
char hex[41];
|
||||||
|
|
||||||
strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
|
strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV));
|
||||||
|
|
||||||
if (verbosity >= 0)
|
if (verbosity >= 0)
|
||||||
printf(_("Updating %s..%s\n"),
|
printf(_("Updating %s..%s\n"),
|
||||||
|
@ -1252,10 +1260,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
if (!o)
|
if (!o)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (checkout_fast_forward(head, remoteheads->item->object.sha1))
|
if (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
finish(o->sha1, msg.buf);
|
finish(head_commit, o->sha1, msg.buf);
|
||||||
drop_save();
|
drop_save();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!remoteheads->next && common->next)
|
} else if (!remoteheads->next && common->next)
|
||||||
|
@ -1275,8 +1283,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
git_committer_info(IDENT_ERROR_ON_NO_NAME);
|
||||||
printf(_("Trying really trivial in-index merge...\n"));
|
printf(_("Trying really trivial in-index merge...\n"));
|
||||||
if (!read_tree_trivial(common->item->object.sha1,
|
if (!read_tree_trivial(common->item->object.sha1,
|
||||||
head, remoteheads->item->object.sha1))
|
head_commit->object.sha1, remoteheads->item->object.sha1))
|
||||||
return merge_trivial();
|
return merge_trivial(head_commit);
|
||||||
printf(_("Nope.\n"));
|
printf(_("Nope.\n"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1295,8 +1303,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
* merge_bases again, otherwise "git merge HEAD^
|
* merge_bases again, otherwise "git merge HEAD^
|
||||||
* HEAD^^" would be missed.
|
* HEAD^^" would be missed.
|
||||||
*/
|
*/
|
||||||
common_one = get_merge_bases(lookup_commit(head),
|
common_one = get_merge_bases(head_commit, j->item, 1);
|
||||||
j->item, 1);
|
|
||||||
if (hashcmp(common_one->item->object.sha1,
|
if (hashcmp(common_one->item->object.sha1,
|
||||||
j->item->object.sha1)) {
|
j->item->object.sha1)) {
|
||||||
up_to_date = 0;
|
up_to_date = 0;
|
||||||
|
@ -1323,21 +1330,18 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
* sync with the head commit. The strategies are responsible
|
* sync with the head commit. The strategies are responsible
|
||||||
* to ensure this.
|
* to ensure this.
|
||||||
*/
|
*/
|
||||||
if (use_strategies_nr != 1) {
|
if (use_strategies_nr == 1 ||
|
||||||
/*
|
/*
|
||||||
* Stash away the local changes so that we can try more
|
* Stash away the local changes so that we can try more than one.
|
||||||
* than one.
|
*/
|
||||||
*/
|
save_state(stash))
|
||||||
save_state();
|
hashcpy(stash, null_sha1);
|
||||||
} else {
|
|
||||||
memcpy(stash, null_sha1, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < use_strategies_nr; i++) {
|
for (i = 0; i < use_strategies_nr; i++) {
|
||||||
int ret;
|
int ret;
|
||||||
if (i) {
|
if (i) {
|
||||||
printf(_("Rewinding the tree to pristine...\n"));
|
printf(_("Rewinding the tree to pristine...\n"));
|
||||||
restore_state();
|
restore_state(head_commit->object.sha1, stash);
|
||||||
}
|
}
|
||||||
if (use_strategies_nr != 1)
|
if (use_strategies_nr != 1)
|
||||||
printf(_("Trying merge strategy %s...\n"),
|
printf(_("Trying merge strategy %s...\n"),
|
||||||
|
@ -1349,7 +1353,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
wt_strategy = use_strategies[i]->name;
|
wt_strategy = use_strategies[i]->name;
|
||||||
|
|
||||||
ret = try_merge_strategy(use_strategies[i]->name,
|
ret = try_merge_strategy(use_strategies[i]->name,
|
||||||
common, head_arg);
|
common, head_commit, head_arg);
|
||||||
if (!option_commit && !ret) {
|
if (!option_commit && !ret) {
|
||||||
merge_was_ok = 1;
|
merge_was_ok = 1;
|
||||||
/*
|
/*
|
||||||
|
@ -1391,14 +1395,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
* auto resolved the merge cleanly.
|
* auto resolved the merge cleanly.
|
||||||
*/
|
*/
|
||||||
if (automerge_was_ok)
|
if (automerge_was_ok)
|
||||||
return finish_automerge(common, result_tree, wt_strategy);
|
return finish_automerge(head_commit, common, result_tree,
|
||||||
|
wt_strategy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pick the result from the best strategy and have the user fix
|
* Pick the result from the best strategy and have the user fix
|
||||||
* it up.
|
* it up.
|
||||||
*/
|
*/
|
||||||
if (!best_strategy) {
|
if (!best_strategy) {
|
||||||
restore_state();
|
restore_state(head_commit->object.sha1, stash);
|
||||||
if (use_strategies_nr > 1)
|
if (use_strategies_nr > 1)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
_("No merge strategy handled the merge.\n"));
|
_("No merge strategy handled the merge.\n"));
|
||||||
|
@ -1410,14 +1415,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||||
; /* We already have its result in the working tree. */
|
; /* We already have its result in the working tree. */
|
||||||
else {
|
else {
|
||||||
printf(_("Rewinding the tree to pristine...\n"));
|
printf(_("Rewinding the tree to pristine...\n"));
|
||||||
restore_state();
|
restore_state(head_commit->object.sha1, stash);
|
||||||
printf(_("Using the %s to prepare resolving by hand.\n"),
|
printf(_("Using the %s to prepare resolving by hand.\n"),
|
||||||
best_strategy);
|
best_strategy);
|
||||||
try_merge_strategy(best_strategy, common, head_arg);
|
try_merge_strategy(best_strategy, common, head_commit, head_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (squash)
|
if (squash)
|
||||||
finish(NULL, NULL);
|
finish(head_commit, NULL, NULL);
|
||||||
else {
|
else {
|
||||||
int fd;
|
int fd;
|
||||||
struct commit_list *j;
|
struct commit_list *j;
|
||||||
|
|
12
commit.c
12
commit.c
|
@ -39,6 +39,18 @@ struct commit *lookup_commit_reference(const unsigned char *sha1)
|
||||||
return lookup_commit_reference_gently(sha1, 0);
|
return lookup_commit_reference_gently(sha1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name)
|
||||||
|
{
|
||||||
|
struct commit *c = lookup_commit_reference(sha1);
|
||||||
|
if (!c)
|
||||||
|
die(_("could not parse %s"), ref_name);
|
||||||
|
if (hashcmp(sha1, c->object.sha1)) {
|
||||||
|
warning(_("%s %s is not a commit!"),
|
||||||
|
ref_name, sha1_to_hex(sha1));
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
struct commit *lookup_commit(const unsigned char *sha1)
|
struct commit *lookup_commit(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
struct object *obj = lookup_object(sha1);
|
struct object *obj = lookup_object(sha1);
|
||||||
|
|
7
commit.h
7
commit.h
|
@ -38,6 +38,13 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
|
||||||
int quiet);
|
int quiet);
|
||||||
struct commit *lookup_commit_reference_by_name(const char *name);
|
struct commit *lookup_commit_reference_by_name(const char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up object named by "sha1", dereference tag as necessary,
|
||||||
|
* get a commit and return it. If "sha1" does not dereference to
|
||||||
|
* a commit, use ref_name to report an error and die.
|
||||||
|
*/
|
||||||
|
struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name);
|
||||||
|
|
||||||
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
|
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
|
||||||
int parse_commit(struct commit *item);
|
int parse_commit(struct commit *item);
|
||||||
|
|
||||||
|
|
|
@ -1606,10 +1606,10 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
|
||||||
strbuf_release(&buffer);
|
strbuf_release(&buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verify_merge_base(unsigned char *head_sha1, unsigned char *branch_sha1)
|
static int verify_merge_base(unsigned char *head_sha1, struct ref *remote)
|
||||||
{
|
{
|
||||||
struct commit *head = lookup_commit(head_sha1);
|
struct commit *head = lookup_commit_or_die(head_sha1, "HEAD");
|
||||||
struct commit *branch = lookup_commit(branch_sha1);
|
struct commit *branch = lookup_commit_or_die(remote->old_sha1, remote->name);
|
||||||
struct commit_list *merge_bases = get_merge_bases(head, branch, 1);
|
struct commit_list *merge_bases = get_merge_bases(head, branch, 1);
|
||||||
|
|
||||||
return (merge_bases && !merge_bases->next && merge_bases->item == branch);
|
return (merge_bases && !merge_bases->next && merge_bases->item == branch);
|
||||||
|
@ -1680,7 +1680,7 @@ static int delete_remote_branch(const char *pattern, int force)
|
||||||
return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, sha1_to_hex(remote_ref->old_sha1));
|
return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, sha1_to_hex(remote_ref->old_sha1));
|
||||||
|
|
||||||
/* Remote branch must be an ancestor of remote HEAD */
|
/* Remote branch must be an ancestor of remote HEAD */
|
||||||
if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) {
|
if (!verify_merge_base(head_sha1, remote_ref)) {
|
||||||
return error("The branch '%s' is not an ancestor "
|
return error("The branch '%s' is not an ancestor "
|
||||||
"of your current HEAD.\n"
|
"of your current HEAD.\n"
|
||||||
"If you are sure you want to delete it,"
|
"If you are sure you want to delete it,"
|
||||||
|
|
|
@ -1052,10 +1052,12 @@ static void prepare_show_merge(struct rev_info *revs)
|
||||||
const char **prune = NULL;
|
const char **prune = NULL;
|
||||||
int i, prune_num = 1; /* counting terminating NULL */
|
int i, prune_num = 1; /* counting terminating NULL */
|
||||||
|
|
||||||
if (get_sha1("HEAD", sha1) || !(head = lookup_commit(sha1)))
|
if (get_sha1("HEAD", sha1))
|
||||||
die("--merge without HEAD?");
|
die("--merge without HEAD?");
|
||||||
if (get_sha1("MERGE_HEAD", sha1) || !(other = lookup_commit(sha1)))
|
head = lookup_commit_or_die(sha1, "HEAD");
|
||||||
|
if (get_sha1("MERGE_HEAD", sha1))
|
||||||
die("--merge without MERGE_HEAD?");
|
die("--merge without MERGE_HEAD?");
|
||||||
|
other = lookup_commit_or_die(sha1, "MERGE_HEAD");
|
||||||
add_pending_object(revs, &head->object, "HEAD");
|
add_pending_object(revs, &head->object, "HEAD");
|
||||||
add_pending_object(revs, &other->object, "MERGE_HEAD");
|
add_pending_object(revs, &other->object, "MERGE_HEAD");
|
||||||
bases = get_merge_bases(head, other, 1);
|
bases = get_merge_bases(head, other, 1);
|
||||||
|
|
Loading…
Reference in a new issue