From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Junio C Hamano <gitster@pobox.com>
Cc: "Gerrit Pape" <pape@smarden.org>,
git@vger.kernel.org, "Rémi Vanicat" <vanicat@debian.org>
Subject: [PATCH 1/2] merge-recursive: sometimes, d/f conflict is not an issue
Date: Tue, 17 Jul 2007 18:13:12 +0100 (BST) [thread overview]
Message-ID: <Pine.LNX.4.64.0707171812490.14781@racer.site> (raw)
In-Reply-To: <7v8x9q1x5t.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 3697 bytes --]
When a merge has a d/f conflict on a path which was not touched
between the merge base(s) and the remote HEAD, and the index and
HEAD contain the same version for that path (even if empty), it
is not really a conflict.
Noticed by Rémi Vanicat, reported to the Git list by Gerrit Pape.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Turns out I was wrong with my "this is only half of it" remark.
AFAICT "merge-tree -u -m" does not touch the files which have
unmerged entries, but merge-recursive does. And since
fix_up_df_conflicts() is called before any of that, it just works.
merge-recursive.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index c8539ec..fb487ba 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -243,6 +243,91 @@ static int git_merge_trees(int index_only,
return rc;
}
+/*
+ * If there were dir/file conflicts, which are not really dir/file
+ * conflicts, because only one side changed anything, take that
+ * side instead of outputting silly conflicts.
+ *
+ * We keep it nice and easy, in that we only fix the conflicts if one
+ * side was renamed without changing the contents _at all_. We check that
+ * by comparing the hash.
+ */
+static inline int is_df(struct cache_entry *in_dir, struct cache_entry *file)
+{
+ int len = ce_namelen(file);
+ const char *name = in_dir->name;
+ return !memcmp(name, file->name, len) && name[len] == '/';
+}
+
+static int fix_up_df_conflicts(const unsigned char *base,
+ const unsigned char *head, const unsigned char *merge)
+{
+ int i;
+ for (i = 0; i + 2 < active_nr; i++) {
+ int last;
+ unsigned char sha1[20], sha2[20];
+ unsigned dummy;
+ char *name;
+ struct cache_entry *ce = active_cache[i], *ce1, *ce2;
+
+ if (ce_stage(ce) == 0)
+ continue;
+ ce1 = active_cache[i + 1];
+ ce2 = active_cache[i + 2];
+ if (ce_same_name(ce, ce2) || !is_df(ce2, ce)) {
+ /* not a d/f conflict */
+ i += 2;
+ continue;
+ }
+ for (last = i + 3; last < active_nr &&
+ is_df(active_cache[last], ce); last++)
+ ; /* do nothing */
+ /* check if unchanged in HEAD */
+ if (ce_same_name(ce, ce1)) {
+ if (ce_stage(ce) != 1 ||
+ hashcmp(ce->sha1, ce1->sha1)) {
+ /* file was changed */
+ i = last - 1;
+ continue;
+ }
+ /* other side removed file, added dir */
+ if (!remove_file_from_cache(ce->name))
+ return error("index error");
+ for (i -= 2, last -= 2; i < last; i++)
+ active_cache[i]->ce_flags &=
+ ~ntohs(CE_STAGEMASK);
+ i--;
+ continue;
+ }
+ if (i + 1 == last)
+ continue;
+ /* check if HEAD changed type (e.g. dir->file) */
+ if (ce_stage(ce) == 1) {
+ i = last - 1;
+ continue;
+ }
+ name = xstrndup(ce->name, ce_namelen(ce));
+ if (get_tree_entry(base, name, sha1, &dummy) ||
+ get_tree_entry(ce_stage(ce) == 2 ?
+ merge : head,
+ name, sha2, &dummy)) {
+ free(name);
+ i = last - 1;
+ continue;
+ }
+ free(name);
+ if (!hashcmp(sha1, sha2)) {
+ /* remove tree */
+ memmove(active_cache + i + 1, active_cache + last,
+ (active_nr - last) *
+ sizeof(struct cache_entry *));
+ active_nr -= last - i - 1;
+ ce->ce_flags &= ~ntohs(CE_STAGEMASK);
+ }
+ }
+ return 0;
+}
+
static int unmerged_index(void)
{
int i;
@@ -1542,6 +1627,8 @@ static int merge_trees(struct tree *head,
sha1_to_hex(head->object.sha1),
sha1_to_hex(merge->object.sha1));
+ fix_up_df_conflicts(common->object.sha1,
+ head->object.sha1, merge->object.sha1);
if (unmerged_index()) {
struct path_list *entries, *re_head, *re_merge;
int i;
--
1.5.3.rc1.16.g9d6f-dirty
next prev parent reply other threads:[~2007-07-17 17:14 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20070405071615.2915.6837.reportbug@acer>
[not found] ` <20070607074357.27760.qmail@69aef7b888effd.315fe32.mid.smarden.org>
[not found] ` <6b8a91420706070252y3fd581a3w427d91e5b982d29d@mail.gmail.com>
2007-06-13 9:16 ` unexpected git-cherry-pick conflict Gerrit Pape
2007-06-13 12:58 ` Johannes Schindelin
2007-06-13 13:43 ` Gerrit Pape
2007-06-13 14:43 ` Johannes Schindelin
2007-06-25 7:18 ` Gerrit Pape
2007-06-25 7:55 ` Johannes Schindelin
2007-07-07 20:58 ` Johannes Schindelin
2007-12-21 10:37 ` Gerrit Pape
2007-12-22 8:20 ` Junio C Hamano
2007-07-08 0:52 ` [PATCH] merge-tree: sometimes, d/f conflict is not an issue Johannes Schindelin
2007-07-08 1:31 ` Junio C Hamano
2007-07-08 2:00 ` Johannes Schindelin
2007-07-08 2:18 ` Johannes Schindelin
2007-07-08 4:35 ` Johannes Schindelin
2007-07-08 5:50 ` Junio C Hamano
2007-07-08 6:14 ` Junio C Hamano
2007-07-08 13:16 ` Johannes Schindelin
2007-07-08 20:02 ` Junio C Hamano
2007-07-09 15:06 ` merge-one-file, was " Johannes Schindelin
2007-07-17 17:13 ` Johannes Schindelin [this message]
2007-08-08 14:39 ` [PATCH 1/2] merge-recursive: " Gerrit Pape
2007-07-17 17:14 ` [PATCH 2/2] Add tests for cherry-pick d/f conflict which should be none Johannes Schindelin
2007-07-08 12:53 ` [PATCH] merge-tree: sometimes, d/f conflict is not an issue Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0707171812490.14781@racer.site \
--to=johannes.schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pape@smarden.org \
--cc=vanicat@debian.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).