|
|
|
@ -46,7 +46,7 @@ static const char * const builtin_merge_usage[] = {
@@ -46,7 +46,7 @@ static const char * const builtin_merge_usage[] = {
|
|
|
|
|
|
|
|
|
|
static int show_diffstat = 1, shortlog_len, squash; |
|
|
|
|
static int option_commit = 1, allow_fast_forward = 1; |
|
|
|
|
static int fast_forward_only; |
|
|
|
|
static int fast_forward_only, option_edit; |
|
|
|
|
static int allow_trivial = 1, have_message; |
|
|
|
|
static struct strbuf merge_msg; |
|
|
|
|
static struct commit_list *remoteheads; |
|
|
|
@ -189,6 +189,8 @@ static struct option builtin_merge_options[] = {
@@ -189,6 +189,8 @@ static struct option builtin_merge_options[] = {
|
|
|
|
|
"create a single commit instead of doing a merge"), |
|
|
|
|
OPT_BOOLEAN(0, "commit", &option_commit, |
|
|
|
|
"perform a commit if the merge succeeds (default)"), |
|
|
|
|
OPT_BOOLEAN('e', "edit", &option_edit, |
|
|
|
|
"edit message before committing"), |
|
|
|
|
OPT_BOOLEAN(0, "ff", &allow_fast_forward, |
|
|
|
|
"allow fast-forward (default)"), |
|
|
|
|
OPT_BOOLEAN(0, "ff-only", &fast_forward_only, |
|
|
|
@ -843,30 +845,54 @@ static void add_strategies(const char *string, unsigned attr)
@@ -843,30 +845,54 @@ static void add_strategies(const char *string, unsigned attr)
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void write_merge_msg(void) |
|
|
|
|
static void write_merge_msg(struct strbuf *msg) |
|
|
|
|
{ |
|
|
|
|
int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); |
|
|
|
|
if (fd < 0) |
|
|
|
|
die_errno(_("Could not open '%s' for writing"), |
|
|
|
|
git_path("MERGE_MSG")); |
|
|
|
|
if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len) |
|
|
|
|
if (write_in_full(fd, msg->buf, msg->len) != msg->len) |
|
|
|
|
die_errno(_("Could not write to '%s'"), git_path("MERGE_MSG")); |
|
|
|
|
close(fd); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void read_merge_msg(void) |
|
|
|
|
static void read_merge_msg(struct strbuf *msg) |
|
|
|
|
{ |
|
|
|
|
strbuf_reset(&merge_msg); |
|
|
|
|
if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0) |
|
|
|
|
strbuf_reset(msg); |
|
|
|
|
if (strbuf_read_file(msg, git_path("MERGE_MSG"), 0) < 0) |
|
|
|
|
die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void run_prepare_commit_msg(void) |
|
|
|
|
static void write_merge_state(void); |
|
|
|
|
static void abort_commit(const char *err_msg) |
|
|
|
|
{ |
|
|
|
|
write_merge_msg(); |
|
|
|
|
if (err_msg) |
|
|
|
|
error("%s", err_msg); |
|
|
|
|
fprintf(stderr, |
|
|
|
|
_("Not committing merge; use 'git commit' to complete the merge.\n")); |
|
|
|
|
write_merge_state(); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
read_merge_msg(); |
|
|
|
|
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 int merge_trivial(struct commit *head) |
|
|
|
@ -880,7 +906,7 @@ static int merge_trivial(struct commit *head)
@@ -880,7 +906,7 @@ static int merge_trivial(struct commit *head)
|
|
|
|
|
parent->next = xmalloc(sizeof(*parent->next)); |
|
|
|
|
parent->next->item = remoteheads->item; |
|
|
|
|
parent->next->next = NULL; |
|
|
|
|
run_prepare_commit_msg(); |
|
|
|
|
prepare_to_commit(); |
|
|
|
|
commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL); |
|
|
|
|
finish(head, result_commit, "In-index merge"); |
|
|
|
|
drop_save(); |
|
|
|
@ -909,9 +935,9 @@ static int finish_automerge(struct commit *head,
@@ -909,9 +935,9 @@ static int finish_automerge(struct commit *head,
|
|
|
|
|
for (j = remoteheads; j; j = j->next) |
|
|
|
|
pptr = &commit_list_insert(j->item, pptr)->next; |
|
|
|
|
} |
|
|
|
|
free_commit_list(remoteheads); |
|
|
|
|
strbuf_addch(&merge_msg, '\n'); |
|
|
|
|
run_prepare_commit_msg(); |
|
|
|
|
prepare_to_commit(); |
|
|
|
|
free_commit_list(remoteheads); |
|
|
|
|
commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL); |
|
|
|
|
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy); |
|
|
|
|
finish(head, result_commit, buf.buf); |
|
|
|
@ -1018,6 +1044,36 @@ static int setup_with_upstream(const char ***argv)
@@ -1018,6 +1044,36 @@ static int setup_with_upstream(const char ***argv)
|
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void write_merge_state(void) |
|
|
|
|
{ |
|
|
|
|
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)); |
|
|
|
|
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(&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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int cmd_merge(int argc, const char **argv, const char *prefix) |
|
|
|
|
{ |
|
|
|
|
unsigned char result_tree[20]; |
|
|
|
@ -1423,33 +1479,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
@@ -1423,33 +1479,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|
|
|
|
|
|
|
|
|
if (squash) |
|
|
|
|
finish(head_commit, 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); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
write_merge_state(); |
|
|
|
|
|
|
|
|
|
if (merge_was_ok) { |
|
|
|
|
fprintf(stderr, _("Automatic merge went well; " |
|
|
|
|