+static int merged_entry(struct cache_entry *merge, struct cache_entry *old, struct cache_entry **dst)
+{
+ merge->ce_flags |= htons(CE_UPDATE);
+ if (old) {
+ /*
+ * See if we can re-use the old CE directly?
+ * That way we get the uptodate stat info.
+ *
+ * This also removes the UPDATE flag on
+ * a match.
+ */
+ if (same(old, merge)) {
+ *merge = *old;
+ } else {
+ verify_uptodate(old);
+ }
+ }
+ merge->ce_flags &= ~htons(CE_STAGEMASK);
+ *dst++ = merge;
+ return 1;
+}
+
+static int threeway_merge(struct cache_entry *stages[4], struct cache_entry **dst)
+{
+ struct cache_entry *old = stages[0];
+ struct cache_entry *a = stages[1], *b = stages[2], *c = stages[3];
+ struct cache_entry *merge;
+ int count;
+
+ /*
+ * If we have an entry in the index cache ("old"), then we want
+ * to make sure that it matches any entries in stage 2 ("first
+ * branch", aka "b").
+ */
+ if (old) {
+ if (!b || !same(old, b))
+ return -1;
+ }
+ merge = merge_entries(a, b, c);
+ if (merge)
+ return merged_entry(merge, old, dst);
+ if (old)
+ verify_uptodate(old);
+ count = 0;
+ if (a) { *dst++ = a; count++; }
+ if (b) { *dst++ = b; count++; }
+ if (c) { *dst++ = c; count++; }
+ return count;
+}
+
+/*
+ * Two-way merge.
+ *
+ * The rule is to "carry forward" what is in the index without losing
+ * information across a "fast forward", favoring a successful merge
+ * over a merge failure when it makes sense. For details of the
+ * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
+ *
+ */
+static int twoway_merge(struct cache_entry **src, struct cache_entry **dst)
+{
+ struct cache_entry *current = src[0];
+ struct cache_entry *oldtree = src[1], *newtree = src[2];
+
+ if (src[3])
+ return -1;
+
+ if (current) {
+ if ((!oldtree && !newtree) || /* 4 and 5 */
+ (!oldtree && newtree &&
+ same(current, newtree)) || /* 6 and 7 */
+ (oldtree && newtree &&
+ same(oldtree, newtree)) || /* 14 and 15 */
+ (oldtree && newtree &&
+ !same(oldtree, newtree) && /* 18 and 19*/
+ same(current, newtree))) {
+ *dst++ = current;
+ return 1;
+ }
+ else if (oldtree && !newtree && same(current, oldtree)) {
+ /* 10 or 11 */
+ verify_uptodate(current);
+ return 0;