{"thread":{"id":"20589","subject":"merging individual files","startedAt":"2009-08-13T20:16:52Z","lastAt":"2009-08-14T16:14:34Z","messageCount":6,"participants":["Chris Marshall","Michael J Gruber"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"120575","messageId":"loom.20090813T192334-7@post.gmane.org","threadId":"20589","inReplyTo":null,"subject":"merging individual files","fromName":"Chris Marshall","fromEmail":"christopher.marshall@merchantlink.com","sentAt":"2009-08-13T20:16:52Z","receivedAt":"2009-08-13T20:16:52Z","isPatch":false,"sender":{"key":"christopher.marshall@merchantlink.com","avatar":null},"body":"Suppose that merging branch dev1 into master would result in three files, f1,\nf2, and f3 being changed, and that I only want to merge the changes for f1 and\nf2 and not the changes for f3 currently.  Later on, I want to accept the f3\nchanges.  Suppose further that the changes to f1, f2, and f3 occurred in a\nsingle commit to branch dev1.\n\nWhat is the simplest way to use git to achieve that effect?\n\nMore generally, I need a way to accept the changes for one or two files while\nrejecting the changes for a potentially large number of files, then later on \naccepting the changes for the large number of files.\n\nI work at a company where perforce is currently used for all development and am\ntrying to work out the git equivalents to all of the perforce flows we use. \nThis workflow is the only one that I am stumped on.\n\nOne solution that occurs to me is to create a temporary branch off of the (most\nrecent) common ancestor of master and br1, let's say br2, checkout the files\nfrom br1 that I want to merge into master and commit those to br2, then merge\nbr2 into master:\n\ngit checkout common_ancestor_commit\ngit checkout -b br2\ngit checkout br1 f1 f2\ngit commit\ngit checkout master\ngit merge br2\ngit branch -d br2\n\nThis strikes me as not too bad of a procedure, as long as there is a graceful\nway of determining the most recent common ancestor of br1 and master.  What's\nthe simplest way of doing that?\n"},{"id":"120624","messageId":"4A851887.5010701@drmicha.warpmail.net","threadId":"20589","inReplyTo":"loom.20090813T192334-7@post.gmane.org","subject":"Re: merging individual files","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-08-14T07:55:51Z","receivedAt":"2009-08-14T07:55:51Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Chris Marshall venit, vidit, dixit 13.08.2009 22:16:\n> Suppose that merging branch dev1 into master would result in three files, f1,\n> f2, and f3 being changed, and that I only want to merge the changes for f1 and\n> f2 and not the changes for f3 currently.  Later on, I want to accept the f3\n> changes.  Suppose further that the changes to f1, f2, and f3 occurred in a\n> single commit to branch dev1.\n> \n> What is the simplest way to use git to achieve that effect?\n> \n> More generally, I need a way to accept the changes for one or two files while\n> rejecting the changes for a potentially large number of files, then later on \n> accepting the changes for the large number of files.\n> \n> I work at a company where perforce is currently used for all development and am\n> trying to work out the git equivalents to all of the perforce flows we use. \n> This workflow is the only one that I am stumped on.\n> \n> One solution that occurs to me is to create a temporary branch off of the (most\n> recent) common ancestor of master and br1, let's say br2, checkout the files\n> from br1 that I want to merge into master and commit those to br2, then merge\n> br2 into master:\n> \n> git checkout common_ancestor_commit\n> git checkout -b br2\n> git checkout br1 f1 f2\n> git commit\n> git checkout master\n> git merge br2\n> git branch -d br2\n> \n> This strikes me as not too bad of a procedure, as long as there is a graceful\n> way of determining the most recent common ancestor of br1 and master.  What's\n> the simplest way of doing that?\n> \n\nThat would be simply git merge-base master br1.\n\nBUT: The main problem here is that git is not file based, but\nrevision/commit/tree based. In the above, you're basically losing all\nthe history common_ancestor_commit..br1 which produced br1's version of\nf1 and f2, in the sense that a git log master will not show that part of\nthe history at all.\n\nIf it makes sense to change f1 and f2 without changing f3 that probably\nmeans that the pertinent commit should have been split. Is it an option\nfor you to rewrite br1's history? That would be the most gittish solution.\n\nAlternatively, you could\ngit checkout master\ngit merge --no-commit br1\ngit checkout --ours f3\ngit commit # add a note about f3 in the commit message\n\nThat way at least you have the full history on master. Note that this\nwill tell git that br1 is merged in, that is you can't use merge later\non to pull in the changes to f3.\nThen, when you want to get that change to f3, you can br1's version of\nf3 using git checkout br1 -- f3 and committing that to master. But you\nshould really rewrite br1 ;)\n\nMichael\n"},{"id":"120636","messageId":"loom.20090814T135614-375@post.gmane.org","threadId":"20589","inReplyTo":"4A851887.5010701@drmicha.warpmail.net","subject":"Re: merging individual files","fromName":"Chris Marshall","fromEmail":"christopher.marshall@merchantlink.com","sentAt":"2009-08-14T14:31:17Z","receivedAt":"2009-08-14T14:31:17Z","isPatch":false,"sender":{"key":"christopher.marshall@merchantlink.com","avatar":null},"body":"Michael J Gruber <git <at> drmicha.warpmail.net> writes:\n> > This strikes me as not too bad of a procedure, as long as there is a \ngraceful\n> > way of determining the most recent common ancestor of br1 and master.  \nWhat's\n> > the simplest way of doing that?\n> > \n> \n> That would be simply git merge-base master br1.\n> \n> BUT: The main problem here is that git is not file based, but\n> revision/commit/tree based. In the above, you're basically losing all\n> the history common_ancestor_commit..br1 which produced br1's version of\n> f1 and f2, in the sense that a git log master will not show that part of\n> the history at all.\n\nWell put, I agree.  One of the main arguments I am going to use to try to \nconvince my fellows to switch from perforce to git is the usefulness of git \nblame.  I would be defeating that with my procedure.\n\n> \n> If it makes sense to change f1 and f2 without changing f3 that probably\n> means that the pertinent commit should have been split. Is it an option\n> for you to rewrite br1's history? That would be the most gittish solution.\n\nYes, I like the idea of rewriting br1's history.\n\nSo, given that f1, f2, ..., fn were changed together in one commit X on br1, I \nwant to break f1 and f2 out of X and put them into X', then leave the rest of \nthe f3,...,fn changes in Y'.\n\nLet's say X was the last commit on br1.  \n\nWhat would the commands to do that look like?\n"},{"id":"120638","messageId":"4A858298.4020702@drmicha.warpmail.net","threadId":"20589","inReplyTo":"loom.20090814T135614-375@post.gmane.org","subject":"Re: merging individual files","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-08-14T15:28:24Z","receivedAt":"2009-08-14T15:28:24Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Chris Marshall venit, vidit, dixit 14.08.2009 16:31:\n> Michael J Gruber <git <at> drmicha.warpmail.net> writes:\n>>> This strikes me as not too bad of a procedure, as long as there is a \n> graceful\n>>> way of determining the most recent common ancestor of br1 and master.  \n> What's\n>>> the simplest way of doing that?\n>>>\n>>\n>> That would be simply git merge-base master br1.\n>>\n>> BUT: The main problem here is that git is not file based, but\n>> revision/commit/tree based. In the above, you're basically losing all\n>> the history common_ancestor_commit..br1 which produced br1's version of\n>> f1 and f2, in the sense that a git log master will not show that part of\n>> the history at all.\n> \n> Well put, I agree.  One of the main arguments I am going to use to try to \n> convince my fellows to switch from perforce to git is the usefulness of git \n> blame.  I would be defeating that with my procedure.\n> \n>>\n>> If it makes sense to change f1 and f2 without changing f3 that probably\n>> means that the pertinent commit should have been split. Is it an option\n>> for you to rewrite br1's history? That would be the most gittish solution.\n> \n> Yes, I like the idea of rewriting br1's history.\n> \n> So, given that f1, f2, ..., fn were changed together in one commit X on br1, I \n> want to break f1 and f2 out of X and put them into X', then leave the rest of \n> the f3,...,fn changes in Y'.\n> \n> Let's say X was the last commit on br1.  \n> \n> What would the commands to do that look like?\n> \n\nIf you're on br1, I would:\n\ngit rebase -i X^\n# change \"pick\" to \"edit\" in front of X in the list you get\ngit checkout X^ -- f3 f4 f5\ngit commit --amend\ngit checkout X -- f3 f4 f5\ngit commit\n\nFor the 2nd commit, using the -c option may be beneficial.\n\nCheers,\nMichael\n"},{"id":"120641","messageId":"4A858B3B.3000208@drmicha.warpmail.net","threadId":"20589","inReplyTo":"4A858298.4020702@drmicha.warpmail.net","subject":"Re: merging individual files","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-08-14T16:05:15Z","receivedAt":"2009-08-14T16:05:15Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Michael J Gruber venit, vidit, dixit 14.08.2009 17:28:\n> Chris Marshall venit, vidit, dixit 14.08.2009 16:31:\n>> Michael J Gruber <git <at> drmicha.warpmail.net> writes:\n>>>> This strikes me as not too bad of a procedure, as long as there is a \n>> graceful\n>>>> way of determining the most recent common ancestor of br1 and master.  \n>> What's\n>>>> the simplest way of doing that?\n>>>>\n>>>\n>>> That would be simply git merge-base master br1.\n>>>\n>>> BUT: The main problem here is that git is not file based, but\n>>> revision/commit/tree based. In the above, you're basically losing all\n>>> the history common_ancestor_commit..br1 which produced br1's version of\n>>> f1 and f2, in the sense that a git log master will not show that part of\n>>> the history at all.\n>>\n>> Well put, I agree.  One of the main arguments I am going to use to try to \n>> convince my fellows to switch from perforce to git is the usefulness of git \n>> blame.  I would be defeating that with my procedure.\n>>\n>>>\n>>> If it makes sense to change f1 and f2 without changing f3 that probably\n>>> means that the pertinent commit should have been split. Is it an option\n>>> for you to rewrite br1's history? That would be the most gittish solution.\n>>\n>> Yes, I like the idea of rewriting br1's history.\n>>\n>> So, given that f1, f2, ..., fn were changed together in one commit X on br1, I \n>> want to break f1 and f2 out of X and put them into X', then leave the rest of \n>> the f3,...,fn changes in Y'.\n>>\n>> Let's say X was the last commit on br1.  \n>>\n>> What would the commands to do that look like?\n>>\n> \n> If you're on br1, I would:\n> \n> git rebase -i X^\n> # change \"pick\" to \"edit\" in front of X in the list you get\n> git checkout X^ -- f3 f4 f5\n> git commit --amend\n> git checkout X -- f3 f4 f5\n> git commit\n\nfollowed by\n\ngit rebase --continue\n\nof course ;)\n\n> \n> For the 2nd commit, using the -c option may be beneficial.\n> \n> Cheers,\n> Michael\n> \n"},{"id":"120642","messageId":"loom.20090814T160738-200@post.gmane.org","threadId":"20589","inReplyTo":"4A858B3B.3000208@drmicha.warpmail.net","subject":"Re: merging individual files","fromName":"Chris Marshall","fromEmail":"christopher.marshall@merchantlink.com","sentAt":"2009-08-14T16:14:34Z","receivedAt":"2009-08-14T16:14:34Z","isPatch":false,"sender":{"key":"christopher.marshall@merchantlink.com","avatar":null},"body":"Michael J Gruber <git <at> drmicha.warpmail.net> writes:\n> > If you're on br1, I would:\n> > \n> > git rebase -i X^\n> > # change \"pick\" to \"edit\" in front of X in the list you get\n> > git checkout X^ -- f3 f4 f5\n> > git commit --amend\n> > git checkout X -- f3 f4 f5\n> > git commit\n> \n> followed by\n> \n> git rebase --continue\n> \n> of course ;)\n> \n> > \n> > For the 2nd commit, using the -c option may be beneficial.\n> > \n> > Cheers,\n> > Michael\n> > \n> \n> \n\nMichael:\n\nThanks so much for your help, this is a lot of fun!\n\nIt occurs to me that another way (that doesn't use rebase) would be this:\ngit branch -m br1 br1-old\ngit checkout br1-old\ngit reset HEAD~\ngit checkout -b br1\ngit add f1\ngit commit -m \"f1\"\ngit add f2 f3\ngit commit -m \"f2\"\ngit branch -d br1-old (history eraser button ;-)\n\ngit checkout master\ngit merge br1~ (which now only pulls f1's changes)\n(work for a while)\ngit merge br1 (which now pulls f2 and f3).\n\nI like this sequence because it's so explicit about what's going on.\n\nAre there any conceptual problems going this route that I am missing that might\nscrew up history?\n\nChris Marshall\n"}]}