{"thread":{"id":"25506","subject":"Following history of a copied file from another indirect branch","startedAt":"2010-10-21T18:47:01Z","lastAt":"2010-10-22T06:35:17Z","messageCount":4,"participants":["Joshua Jensen","Brian Gernhardt","Johannes Sixt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"153992","messageId":"4CC08AA5.8070502@workspacewhiz.com","threadId":"25506","inReplyTo":null,"subject":"Following history of a copied file from another indirect branch","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2010-10-21T18:47:01Z","receivedAt":"2010-10-21T18:47:01Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"It has become a necessity to copy a file from one long-lived branch to \nanother.  It is not possible to merge the branches at this time.\n\nI would like to have 'git gui blame' follow the copy back through its \noriginal history, but I don't believe Git has metadata for storing \nthis.  Something along the lines of a 'followparent' in the commit \nobject, for instance, would allow the revision walking code to wander \nthe history down an alternate line.\n\nBy comparison, integrates work at a file level in Perforce.  That means \nI can integrate a file from one branch to another, and parentage is \nstored such that I can follow the file back through its history.\n\nAre there any facilities to do this now?\n\nThanks!\n\nJosh\n"},{"id":"154011","messageId":"9089D1F5-A19B-4030-A6ED-463F250E450B@gernhardtsoftware.com","threadId":"25506","inReplyTo":"4CC08AA5.8070502@workspacewhiz.com","subject":"Re: Following history of a copied file from another indirect branch","fromName":"Brian Gernhardt","fromEmail":"brian@gernhardtsoftware.com","sentAt":"2010-10-21T19:39:51Z","receivedAt":"2010-10-21T19:39:51Z","isPatch":false,"sender":{"key":"brian@gernhardtsoftware.com","avatar":"https://avatars.githubusercontent.com/u/133455?v=4"},"body":"\nOn Oct 21, 2010, at 2:47 PM, Joshua Jensen wrote:\n\n> It has become a necessity to copy a file from one long-lived branch to another.  It is not possible to merge the branches at this time.\n> \n> I would like to have 'git gui blame' follow the copy back through its original history, but I don't believe Git has metadata for storing this.  Something along the lines of a 'followparent' in the commit object, for instance, would allow the revision walking code to wander the history down an alternate line.\n\nGit stores no per-file metadata.  The closest we come is .gitattributes and .gitignore.\n\n> By comparison, integrates work at a file level in Perforce.  That means I can integrate a file from one branch to another, and parentage is stored such that I can follow the file back through its history.\n> \n> Are there any facilities to do this now?\n\nGit simply does not have the idea of the history of a file.  Nothing in git will help merge \"just a file\" from one branch to another.  Either we have merged the two commits or not.\n\nHOWEVER...\n\nYou can use git-filter-branch to create a new branch that contains only that single file and only the commits that affected it.  Something like the following (untested):\n\n\t# Merging \"file\" from branch \"src\" to branch \"dest\"\n\tgit checkout -b temp src\n\tgit filter-branch --prune-empty --index-filter=\"git read-tree --empty; git add file\"\n\t# Since you describe the branch as \"long-running\", I'd suspect you'll have to wait a while here.\n\tgit checkout dest\n\tgit merge temp\n\tgit branch -d temp\n\tgit branch -D refs/original/temp\n\nThis will go faster if you have a ramdisk/tmpfs to perform the filtering in.  (git-filter-branch is very I/O intensive.)  Something like the following in place of the `git filter-branch` invocation above:\n\n\tmkdir /tmp/filter-branch # Assuming /tmp is tmpfs or similar\n\tgit filter-branch -d /tmp/filter-branch --prune-empty --index-filter=\"git read-tree --empty; git add file\"\n\trm -rf /tmp/filter-branch\n\nYou could use --msg-filter to add the SHA-1 of the original commits to the \"file history\" branch.  Something like --msg-filter='cat;echo;echo From: $GIT_COMMIT'\n\nI would recommend using cherry-pick to pull any further changes to the file across branches (be careful of commits that touch more than that file!).  I think git-filter-branch could be used to keep the one file branch up to date, but that is likely more effort than it's worth.  I would specifically advise against merging the single file branch into both \"src\" and \"dest\", as I think any later merge of the two would find these commits as a merge-base.\n\n~~ Brian Gernhardt\n"},{"id":"154014","messageId":"4CC09D40.4050303@workspacewhiz.com","threadId":"25506","inReplyTo":"9089D1F5-A19B-4030-A6ED-463F250E450B@gernhardtsoftware.com","subject":"Re: Following history of a copied file from another indirect branch","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2010-10-21T20:06:24Z","receivedAt":"2010-10-21T20:06:24Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"----- Original Message -----\nFrom: Brian Gernhardt\nDate: 10/21/2010 1:39 PM\n> On Oct 21, 2010, at 2:47 PM, Joshua Jensen wrote:\n>> It has become a necessity to copy a file from one long-lived branch to another.  It is not possible to merge the branches at this time.\n>>\n>> I would like to have 'git gui blame' follow the copy back through its original history, but I don't believe Git has metadata for storing this.  Something along the lines of a 'followparent' in the commit object, for instance, would allow the revision walking code to wander the history down an alternate line.\n> Git stores no per-file metadata.  The closest we come is .gitattributes and .gitignore.\n>\n>> By comparison, integrates work at a file level in Perforce.  That means I can integrate a file from one branch to another, and parentage is stored such that I can follow the file back through its history.\n>>\n>> Are there any facilities to do this now?\n> Git simply does not have the idea of the history of a file.  Nothing in git will help merge \"just a file\" from one branch to another.  Either we have merged the two commits or not.\nI'm not super interested in per file merging (which is a great concept, \nworks well in Perforce, but is irrelevant here).  I merely want to \npreserve the original parentage so facilities like blame (ultimately \nrev-list?) can walk the extended history.  I'm fine even passing in a \nflag.  I do not care in preserving the original parentage for purposes \nof merging.\n\n> You can use git-filter-branch to create a new branch that contains only that single file and only the commits that affected it.  Something like the following (untested):\n>\n> I would recommend using cherry-pick to pull any further changes to the file across branches (be careful of commits that touch more than that file!).  I think git-filter-branch could be used to keep the one file branch up to date, but that is likely more effort than it's worth.  I would specifically advise against merging the single file branch into both \"src\" and \"dest\", as I think any later merge of the two would find these commits as a merge-base.\nThanks for the info.\n\nThe problem with using cherry-pick is that the commits in question \ncontain more than one file.  Perhaps the individual file should have \nbeen committed separately, but the damage was long ago done.\n\ngit format-patch --stdout HEAD..otherbranch -- the/filename | git \nam           or\ngit diff HEAD..otherbranch -- the/filename | git apply\n\nSeem to be the appropriate methods of copying the file over with fake \nhistory or squashed together.\n\nJosh\n"},{"id":"154106","messageId":"4CC130A5.6050802@viscovery.net","threadId":"25506","inReplyTo":"4CC08AA5.8070502@workspacewhiz.com","subject":"Re: Following history of a copied file from another indirect branch","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2010-10-22T06:35:17Z","receivedAt":"2010-10-22T06:35:17Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 10/21/2010 20:47, schrieb Joshua Jensen:\n> It has become a necessity to copy a file from one long-lived branch to\n> another.  It is not possible to merge the branches at this time.\n> \n> I would like to have 'git gui blame' follow the copy back through its\n> original history, but I don't believe Git has metadata for storing this. \n> Something along the lines of a 'followparent' in the commit object, for\n> instance, would allow the revision walking code to wander the history down\n> an alternate line.\n\nYou can branch off one commit form that long-lived branch that undoes\neverything except the file F you are interested in since the last\nmerge-base. Then you merge that single commit into the other branch.\n\n   ---o--o--B     <- long-lived\n     /  /    \\\n    /  /      U   <- the-file\n   /  /        \\\n -o--A----------M <- master (the other branch)\n\ni.e. 'git diff A..B' shows a lot of changes, but 'git diff A..U' shows\nonly changes to the file you are interested in. 'git diff -R B..U' differs\nfrom 'git diff A..B' only in the changes to the file you are intersted in.\n\nWhen you later find that you need new changes to F that were made on\nlong-lived, but you still cannot merge long-lived, then you can merge\nlong-lived into the-file (resolve conflicts by removing the conflicted\nfiles and also remove newly added files), and then you merge the-file into\nmaster again.\n\nWARNING: When you later merge long-lived into master, the merge will lose\nall changes made on long-lived. You work it around by temporarily grafting\naway the merge parents that point to commits listed by\nlong-lived..the-file. After you complete the merge, you can remove the\ngrafts again.\n\n-- Hannes\n"}]}