{"thread":{"id":"6649","subject":"merge doesn't remove files","startedAt":"2007-02-03T22:48:19Z","lastAt":"2007-02-04T10:40:38Z","messageCount":6,"participants":["Gerrit Pape","Junio C Hamano","Shawn O. Pearce","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"33498","messageId":"20070203224819.20131.qmail@b1b53206edee41.315fe32.mid.smarden.org","threadId":"6649","inReplyTo":null,"subject":"merge doesn't remove files","fromName":"Gerrit Pape","fromEmail":"pape@smarden.org","sentAt":"2007-02-03T22:48:19Z","receivedAt":"2007-02-03T22:48:19Z","isPatch":false,"sender":{"key":"pape@smarden.org","avatar":"https://avatars.githubusercontent.com/u/143170252?v=4"},"body":"Hi, please see http://bugs.debian.org/403104\n\nShouldn't git remove the original file after merging a commit that moved\nthe file away?  Here's a simple test case:\n\n$ mkdir repo && cd repo\n$ git init-db\ndefaulting to local storage area\n$ echo a >foo && git add foo\n$ git commit -a -m'add foo'\nCommitting initial tree 86de5e13286a8449a8a706a58e63be6781770b12\n$ git branch b  \n$ git mv foo bar\n$ git commit -a -m'move foo'\n$ git checkout b\n$ echo ttt >>foo\n$ git commit -a -m'change foo'\n$ git pull . master\nTrying really trivial in-index merge...\nfatal: Merge requires file-level merging\nNope.\nMerging HEAD with adc07a8eac73cdb1cb3764ec50747556ed2abc99\nMerging:\n92eff19 change foo\nadc07a8 move foo\nfound 1 common ancestor(s):\nba043e5 add foo\nMerge made by recursive.\n foo => bar |    0 \n 1 files changed, 0 insertions(+), 0 deletions(-)\n rename foo => bar (100%)\n$ git status\n# On branch refs/heads/b\n# Untracked files:\n#   (use \"git add\" to add to commit)\n#\n#       foo\nnothing to commit\n$ ls\nbar  foo\n$ \n\nThanks, Gerrit.\n"},{"id":"33507","messageId":"7vy7nezr1f.fsf@assigned-by-dhcp.cox.net","threadId":"6649","inReplyTo":"20070203224819.20131.qmail@b1b53206edee41.315fe32.mid.smarden.org","subject":"Re: merge doesn't remove files","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-02-04T00:48:28Z","receivedAt":"2007-02-04T00:48:28Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gerrit Pape <pape@smarden.org> writes:\n\n> Shouldn't git remove the original file after merging a commit that moved\n> the file away?\n\nI think this has been fixed quite a while ago --- does not seem\nto reproduce with the current v1.5.0-rc.\n"},{"id":"33514","messageId":"7vd54qzoka.fsf@assigned-by-dhcp.cox.net","threadId":"6649","inReplyTo":"7vy7nezr1f.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge doesn't remove files","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-02-04T01:41:57Z","receivedAt":"2007-02-04T01:41:57Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> Gerrit Pape <pape@smarden.org> writes:\n>\n>> Shouldn't git remove the original file after merging a commit that moved\n>> the file away?\n>\n> I think this has been fixed quite a while ago --- does not seem\n> to reproduce with the current v1.5.0-rc.\n\nHaving said that, I think there is a worse problem with\nmerge-recursive.  It loses untracked files that are not\ninvolved in the merge.\n\n    $ mkdir repo && cd repo\n    $ git init-db\n    Initialized empty Git repository in .git/\n    $ echo a >foo && git add foo\n    $ git commit -a -m'add foo'\n    Created initial commit da51b094c7c75aef4362e229975be7f376fa00cb\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 foo\n    $ git branch b\n    $ git mv foo bar\n    $ git commit -a -m'move foo'\n    Created commit 3154467cd539db7a90e04b7291442384222de4a4\n     2 files changed, 1 insertions(+), 1 deletions(-)\n     create mode 100644 bar\n     delete mode 100644 foo\n\nThe 'master' branch renames 'foo' to 'bar'\n\n    $ git checkout b\n    Switched to branch \"b\"\n    $ echo ttt >>foo\n    $ git commit -a -m'change foo'\n    Created commit eb14bff5f399b1a9ca6aa450a803833c3f7b7b3a\n     1 files changed, 1 insertions(+), 0 deletions(-)\n\nThe 'b' branch keeps 'foo' but modifies it.\n\n    $ git checkout master\n    Switched to branch \"master\"\n    $ echo frotz >foo\n\nThe 'master' branch has an untracked file 'foo' now.\n\n    $ git merge b\n     100% (5/5) done\n    Merge made by recursive.\n     bar |    1 +\n     1 files changed, 1 insertions(+), 0 deletions(-)\n    $ ls -a\n    ./  ../  bar  .git/\n\nOops.  'foo' is not involved in the merge but is lost.\n\nSadly, a similar case was fixed in merge-resolve where our\nbranch has already removed a file, had an untracked file of the\nsame name in the working tree, and merging an old branch that\nstill had that path.\n\n    $ git init\n    Initialized empty Git repository in .git/\n    $ echo a >foo ; echo b >bar ; git add .\n    $ git commit -m 'initial'\n    Created initial commit 7925ec23146d4bffa1078a2c220df2c2f9935ca8\n     2 files changed, 2 insertions(+), 0 deletions(-)\n     create mode 100644 bar\n     create mode 100644 foo\n    $ git branch b\n    $ rm foo ; echo ttt >>bar\n    $ git commit -a -m 'remove foo and update bar'\n    Created commit 7fbbec4cb0d4af95090e0ba4f1fb8c9630d8e438\n     2 files changed, 1 insertions(+), 1 deletions(-)\n     delete mode 100644 foo\n    $ git checkout b\n    Switched to branch \"b\"\n    $ echo c >baz ; git add .\n    $ git commit -m 'side'\n    Created commit 272ef105f43df5e3629d6915001476651cafa139\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 baz\n    $ git checkout master\n    Switched to branch \"master\"\n    $ ls -a\n    ./  ../  bar  .git/\n    $ echo throw >foo\n    $ git merge -s resolve b\n    Trying really trivial in-index merge...\n    fatal: Merge requires file-level merging\n    Nope.\n    Trying simple merge.\n    Merge made by resolve.\n     baz |    1 +\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 baz\n    $ ls -a\n    ./  ../  bar  baz  foo  .git/\n    $ cat foo\n    throw\n\nFortunately merge-recursive gets this case right, but when a\nrename is involved it does not.\n"},{"id":"33524","messageId":"20070204035037.GB16766@spearce.org","threadId":"6649","inReplyTo":"7vy7nezr1f.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge doesn't remove files","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-02-04T03:50:37Z","receivedAt":"2007-02-04T03:50:37Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Gerrit Pape <pape@smarden.org> writes:\n> \n> > Shouldn't git remove the original file after merging a commit that moved\n> > the file away?\n> \n> I think this has been fixed quite a while ago --- does not seem\n> to reproduce with the current v1.5.0-rc.\n\nIndeed, this commit of mine was supposed to fix it:\n\n  commit 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9\n  Author: Shawn Pearce <spearce@spearce.org>\n  Date:   Wed Dec 13 05:42:44 2006 -0500\n\nIts in 1.5.0-rc0, but nothing earlier.\n\n-- \nShawn.\n"},{"id":"33528","messageId":"20070204045933.GC16766@spearce.org","threadId":"6649","inReplyTo":"7vd54qzoka.fsf@assigned-by-dhcp.cox.net","subject":"Re: merge doesn't remove files","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-02-04T04:59:33Z","receivedAt":"2007-02-04T04:59:33Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Having said that, I think there is a worse problem with\n> merge-recursive.  It loses untracked files that are not\n> involved in the merge.\n\nI tracked it down to my commit 8371234e which was supposed to fix\nthe bug that started this thread.\n\nApparently what I did was make merge-recursive remove the file from\nthe working directory if it was renamed, even though it wasn't in\nthe index when the merge started.\n\nSo merge-recursive is only deleting untracked files which are in\nthe merge base, but aren't in one of the heads involved in the merge.\n\nI'm looking at patching this.  Clearly we should only delete the\nold file from the working directory during a rename if the tree-ish\nwhich was supposed to match the working directory had the file\nin it.  But that tree-ish doesn't have to be the first non-base\nargument to merge-recursive, does it?  In practice it usually is,\nbut can I assume it in the code?\n\nI'm looking at something like the following:\n\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex fa320eb..bbb52a7 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -891,7 +891,7 @@ static int process_renames(struct path_list *a_renames,\n                        struct diff_filespec src_other, dst_other;\n                        int try_merge, stage = a_renames == renames1 ? 3: 2;\n \n-                       remove_file(1, ren1_src, index_only);\n+                       remove_file(1, ren1_src, index_only || stage == 3);\n \n                        hashcpy(src_other.sha1, ren1->src_entry->stages[stage].s\n                        src_other.mode = ren1->src_entry->stages[stage].mode;\n\n-- \nShawn.\n"},{"id":"33564","messageId":"Pine.LNX.4.64.0702040234290.8424@woody.linux-foundation.org","threadId":"6649","inReplyTo":"20070204045933.GC16766@spearce.org","subject":"Re: merge doesn't remove files","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-02-04T10:40:38Z","receivedAt":"2007-02-04T10:40:38Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 3 Feb 2007, Shawn O. Pearce wrote:\n> \n> But that tree-ish doesn't have to be the first non-base\n> argument to merge-recursive, does it?  In practice it usually is,\n> but can I assume it in the code?\n\nYes, the first branch is supposed to be the \"current\" one. That's the one \nwe compare to the index, and that we should already error out on if the \nindex doesn't match the tree. So yeah, a file should ever be removed only \nif it existed in the old index (and by implication in the first branch, \nsince otherwise we should have failed the merge as not having a clean \ntree anyway).\n\n\t\tLinus\n"}]}