{"thread":{"id":"13737","subject":"[PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","startedAt":"2008-05-30T21:43:40Z","lastAt":"2008-05-31T23:50:00Z","messageCount":8,"participants":["Kevin Ballard","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"78185","messageId":"1212183820-40712-1-git-send-email-kevin@sb.org","threadId":"13737","inReplyTo":null,"subject":"[PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2008-05-30T21:43:40Z","receivedAt":"2008-05-30T21:43:40Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"The old description was misleading and logically impossible. It claimed that\nthe ancestors of the original commit would be re-written to have the multiple\nemitted ids as parents. Not only would this modify existing objects, but it\nwould create a cycle. What this actually does is pass the multiple emitted ids\nto the newly-created children to use as parents.\n\nSigned-off-by: Kevin Ballard <kevin@sb.org>\n---\n Documentation/git-filter-branch.txt |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nindex 506c37a..541bf23 100644\n--- a/Documentation/git-filter-branch.txt\n+++ b/Documentation/git-filter-branch.txt\n@@ -113,8 +113,8 @@ OPTIONS\n \tstdin.  The commit id is expected on stdout.\n +\n As a special extension, the commit filter may emit multiple\n-commit ids; in that case, ancestors of the original commit will\n-have all of them as parents.\n+commit ids; in that case, the rewritten children of the original commit will\n+have all of them as parents. You probably don't want to do this.\n +\n You can use the 'map' convenience function in this filter, and other\n convenience functions, too.  For example, calling 'skip_commit \"$@\"'\n-- \n1.5.6.rc0.158.g7c7a1\n"},{"id":"78193","messageId":"7vlk1rh0av.fsf@gitster.siamese.dyndns.org","threadId":"13737","inReplyTo":"1212183820-40712-1-git-send-email-kevin@sb.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-30T22:52:40Z","receivedAt":"2008-05-30T22:52:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kevin Ballard <kevin@sb.org> writes:\n\n> The old description was misleading and logically impossible. It claimed that\n> the ancestors of the original commit would be re-written to have the multiple\n> emitted ids as parents. Not only would this modify existing objects, but it\n> would create a cycle. What this actually does is pass the multiple emitted ids\n> to the newly-created children to use as parents.\n>\n> Signed-off-by: Kevin Ballard <kevin@sb.org>\n> ---\n>  Documentation/git-filter-branch.txt |    4 ++--\n>  1 files changed, 2 insertions(+), 2 deletions(-)\n>\n> diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\n> index 506c37a..541bf23 100644\n> --- a/Documentation/git-filter-branch.txt\n> +++ b/Documentation/git-filter-branch.txt\n> @@ -113,8 +113,8 @@ OPTIONS\n>  \tstdin.  The commit id is expected on stdout.\n>  +\n>  As a special extension, the commit filter may emit multiple\n> -commit ids; in that case, ancestors of the original commit will\n> -have all of them as parents.\n> +commit ids; in that case, the rewritten children of the original commit will\n> +have all of them as parents. You probably don't want to do this.\n>  +\n\nNow I am _very_ confused.\n\nThe original description sounds as if:\n\n        In this history, when rewriting commit C, if we emit A from the\n        filter:\n\n                     B\n                      \\\n                ---A---C---D\n               \n        We will somehow make 'A' and 'B' have A as their parents.\n\nwhich is wrong as you pointed out.\n\nBut I am also confused by the new description:\n\n        In that history, we will make sure that rewritten D (original\n        commit being C) have A as parent.  IOW, we will have\n\n                --A'--C'  D'\n                         /\n                        A\n\nwhich is not what happens.  What it does is that the commits in the output\nfrom the filter (i.e. A) are first mapped to the corresponding commits in\nthe rewritten history (i.e. A'), and they will be used as the parents of\nthe rewritten commit, to form this history:\n\n                --A'--C'\n\nisn't it?\n\nAlso you did not defend why you added \"You probably don't want to do this\"\nto the description.\n"},{"id":"78196","messageId":"98EEBDF4-9964-4CA6-ABBD-DB72C4F6CAD3@sb.org","threadId":"13737","inReplyTo":"7vlk1rh0av.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2008-05-30T23:07:38Z","receivedAt":"2008-05-30T23:07:38Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On May 30, 2008, at 3:52 PM, Junio C Hamano wrote:\n\n> Kevin Ballard <kevin@sb.org> writes:\n>\n>> The old description was misleading and logically impossible. It  \n>> claimed that\n>> the ancestors of the original commit would be re-written to have  \n>> the multiple\n>> emitted ids as parents. Not only would this modify existing  \n>> objects, but it\n>> would create a cycle. What this actually does is pass the multiple  \n>> emitted ids\n>> to the newly-created children to use as parents.\n>>\n>> Signed-off-by: Kevin Ballard <kevin@sb.org>\n>> ---\n>> Documentation/git-filter-branch.txt |    4 ++--\n>> 1 files changed, 2 insertions(+), 2 deletions(-)\n>>\n>> diff --git a/Documentation/git-filter-branch.txt b/Documentation/ \n>> git-filter-branch.txt\n>> index 506c37a..541bf23 100644\n>> --- a/Documentation/git-filter-branch.txt\n>> +++ b/Documentation/git-filter-branch.txt\n>> @@ -113,8 +113,8 @@ OPTIONS\n>> \tstdin.  The commit id is expected on stdout.\n>> +\n>> As a special extension, the commit filter may emit multiple\n>> -commit ids; in that case, ancestors of the original commit will\n>> -have all of them as parents.\n>> +commit ids; in that case, the rewritten children of the original  \n>> commit will\n>> +have all of them as parents. You probably don't want to do this.\n>> +\n>\n> Now I am _very_ confused.\n>\n> The original description sounds as if:\n>\n>        In this history, when rewriting commit C, if we emit A from the\n>        filter:\n>\n>                     B\n>                      \\\n>                ---A---C---D\n>\n>        We will somehow make 'A' and 'B' have A as their parents.\n>\n> which is wrong as you pointed out.\n>\n> But I am also confused by the new description:\n>\n>        In that history, we will make sure that rewritten D (original\n>        commit being C) have A as parent.  IOW, we will have\n>\n>                --A'--C'  D'\n>                         /\n>                        A\n>\n> which is not what happens.  What it does is that the commits in the  \n> output\n> from the filter (i.e. A) are first mapped to the corresponding  \n> commits in\n> the rewritten history (i.e. A'), and they will be used as the  \n> parents of\n> the rewritten commit, to form this history:\n>\n>                --A'--C'\n>\n> isn't it?\n\nSo basically, you think it's missing the fact that the emitted id is  \nmapped to rewritten commits? From reading the git-filter-branch code,  \nI don't think that's correct. When each commit is created, its  \noriginal parents get mapped to new values, but the results of the  \ncommit-filter are dumped straight into the map.\n\nTo give an example, let's examine your tree. A will be processed  \nfirst, and A' gets put into the map for A. B gets processed next (or  \nmaybe before A, but that's irrelevant) and B' gets put into the map  \nfor B. C gets processed, and it emits A, so A goes into the map for C.  \nThen D is processed, and its original parent C is looked up in the map  \nand A is returned. So, as near as I can tell, that \"broken\" history is  \nexactly what you'll get if the commit-filter returns A for C. This  \nmeans that when you're writing a commit-filter for this, you probably  \nwant to emit $(map A), not A.\n\nPerhaps the description should be significantly expanded to include  \nthe diagrams and explanations?\n\n> Also you did not defend why you added \"You probably don't want to do  \n> this\"\n> to the description.\n\n\nBecause when the commit-filter emits multiple ids, it's converting the  \nchild commits into merges without even knowing what the child commits  \nwill be. I was just trying to warn people away from using this feature  \nunless they know exactly what they're doing. Usually you want to use a  \nparent-filter if you're converting commits into merges, because that  \nway you know exactly what commits you're modifying.\n\n-Kevin\n\n-- \nKevin Ballard\nhttp://kevin.sb.org\nkevin@sb.org\nhttp://www.tildesoft.com\n"},{"id":"78199","messageId":"7v63svgy0q.fsf@gitster.siamese.dyndns.org","threadId":"13737","inReplyTo":"98EEBDF4-9964-4CA6-ABBD-DB72C4F6CAD3@sb.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-30T23:41:57Z","receivedAt":"2008-05-30T23:41:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kevin Ballard <kevin@sb.org> writes:\n\n>> But I am also confused by the new description:\n>>\n>>        In that history, we will make sure that rewritten D (original\n>>        commit being C) have A as parent.  IOW, we will have\n>>\n>>                --A'--C'  D'\n>>                         /\n>>                        A\n>>\n>> which is not what happens.  What it does is that the commits in the\n>> output\n>> from the filter (i.e. A) are first mapped to the corresponding\n>> commits in\n>> the rewritten history (i.e. A'), and they will be used as the\n>> parents of\n>> the rewritten commit, to form this history:\n>>\n>>                --A'--C'\n>>\n>> isn't it?\n>\n> So basically, you think it's missing the fact that the emitted id is\n> mapped to rewritten commits? From reading the git-filter-branch code,\n> I don't think that's correct. When each commit is created, its\n> original parents get mapped to new values, but the results of the\n> commit-filter are dumped straight into the map.\n\nAh, I misread this part of the code:\n\n\tparentstr=\n\tfor parent in $parents; do\n\t\tfor reparent in $(map \"$parent\"); do\n\t\t\tparentstr=\"$parentstr -p $reparent\"\n\t\tdone\n\tdone\n\tif [ \"$filter_parent\" ]; then\n\t\tparentstr=\"$(echo \"$parentstr\" | eval \"$filter_parent\")\" ||\n\t\t\t\tdie \"parent filter failed: $filter_parent\"\n\tfi\n\nYou get the commit object names from the new history, and you are supposed\nto give back names from the new history from the filter.\n\nSo \"the rewritten commit will have the output from parent-filter as its\nparents\" is what happens, right?\n\nIOW, in the history in the previous message, when rewriting C (to create\nC'), the filter will get A' and B' (i.e. from the new history), and can\nchoose to return A', and that is recorded when creating C'.  \"the\nrewritten children of the commit\" in your:\n\n    +commit ids; in that case, the rewritten children of the original\n    +commit will have all of them as parents.\n\nsounded as if you are talking about D' not C', and that was what I was\nconfused about.\n\n> To give an example, let's examine your tree. A will be processed\n> first, and A' gets put into the map for A. B gets processed next (or\n> maybe before A, but that's irrelevant) and B' gets put into the map\n> for B. C gets processed, and it emits A, so A goes into the map for C.\n\nHmm?  I meant C is rewritten to become C' but when it does so filter can\nremove B from its parent set (iow, the filter is told that unless it\nintervenes C' will have A' and B' as its parents, but the filter can\nchoose to return only A').  So I do not quite get \"it emits A\" part.  Do\nyou mean \"the filter outputs A'\"?  Also do you mean by \"map\" the mapping\nfrom <A, B, C> to <A', B', C'> commit namespace?  If so, even when the\nfilter \"emits A'\", I do not think it \"goes into the map for C\".  When the\nfilter \"emits A'\", it is used as _the_ single parent to create C', and it\nis C' that \"goes into the map for C\".  Am I still confused?\n\nNow, I admit that I did not look at the implementation of the \"map\" in the\ncode quoted above.  Perhaps that thing is busted, I dunno.\n"},{"id":"78202","messageId":"AF9CB160-FFC9-4372-BE86-5FAC6B59A050@sb.org","threadId":"13737","inReplyTo":"7v63svgy0q.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2008-05-31T00:33:02Z","receivedAt":"2008-05-31T00:33:02Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On May 30, 2008, at 4:41 PM, Junio C Hamano wrote:\n\n> Kevin Ballard <kevin@sb.org> writes:\n>\n>>> But I am also confused by the new description:\n>>>\n>>>       In that history, we will make sure that rewritten D (original\n>>>       commit being C) have A as parent.  IOW, we will have\n>>>\n>>>               --A'--C'  D'\n>>>                        /\n>>>                       A\n>>>\n>>> which is not what happens.  What it does is that the commits in the\n>>> output\n>>> from the filter (i.e. A) are first mapped to the corresponding\n>>> commits in\n>>> the rewritten history (i.e. A'), and they will be used as the\n>>> parents of\n>>> the rewritten commit, to form this history:\n>>>\n>>>               --A'--C'\n>>>\n>>> isn't it?\n>>\n>> So basically, you think it's missing the fact that the emitted id is\n>> mapped to rewritten commits? From reading the git-filter-branch code,\n>> I don't think that's correct. When each commit is created, its\n>> original parents get mapped to new values, but the results of the\n>> commit-filter are dumped straight into the map.\n>\n> Ah, I misread this part of the code:\n>\n> \tparentstr=\n> \tfor parent in $parents; do\n> \t\tfor reparent in $(map \"$parent\"); do\n> \t\t\tparentstr=\"$parentstr -p $reparent\"\n> \t\tdone\n> \tdone\n> \tif [ \"$filter_parent\" ]; then\n> \t\tparentstr=\"$(echo \"$parentstr\" | eval \"$filter_parent\")\" ||\n> \t\t\t\tdie \"parent filter failed: $filter_parent\"\n> \tfi\n>\n> You get the commit object names from the new history, and you are  \n> supposed\n> to give back names from the new history from the filter.\n>\n> So \"the rewritten commit will have the output from parent-filter as  \n> its\n> parents\" is what happens, right?\n>\n> IOW, in the history in the previous message, when rewriting C (to  \n> create\n> C'), the filter will get A' and B' (i.e. from the new history), and  \n> can\n> choose to return A', and that is recorded when creating C'.  \"the\n> rewritten children of the commit\" in your:\n>\n>    +commit ids; in that case, the rewritten children of the original\n>    +commit will have all of them as parents.\n>\n> sounded as if you are talking about D' not C', and that was what I was\n> confused about.\n\nI was talking about D'. You've switched from talking about the commit- \nfilter to talking about the parent-filter.\n\nIf a parent-filter is specified, it will be run on the parents that  \nare handed to the commit-filter (before the commit-filter is invoked),  \nbut that's not relevant right now.\n\nWhen using the commit-filter to rewrite C (to create C'), when A is  \nreturned, that's dumped into the map so in the future, $(map C) will  \nreturn A. This means that when D is processed, it's handed A as the  \nparent.\n\n>> To give an example, let's examine your tree. A will be processed\n>> first, and A' gets put into the map for A. B gets processed next (or\n>> maybe before A, but that's irrelevant) and B' gets put into the map\n>> for B. C gets processed, and it emits A, so A goes into the map for  \n>> C.\n>\n> Hmm?  I meant C is rewritten to become C' but when it does so filter  \n> can\n> remove B from its parent set (iow, the filter is told that unless it\n> intervenes C' will have A' and B' as its parents, but the filter can\n> choose to return only A').  So I do not quite get \"it emits A\"  \n> part.  Do\n> you mean \"the filter outputs A'\"?  Also do you mean by \"map\" the  \n> mapping\n> from <A, B, C> to <A', B', C'> commit namespace?  If so, even when the\n> filter \"emits A'\", I do not think it \"goes into the map for C\".   \n> When the\n> filter \"emits A'\", it is used as _the_ single parent to create C',  \n> and it\n> is C' that \"goes into the map for C\".  Am I still confused?\n>\n> Now, I admit that I did not look at the implementation of the \"map\"  \n> in the\n> code quoted above.  Perhaps that thing is busted, I dunno.\n\n\nYou're still talking about the parent-filter here. I think you're  \nquite confused.\n\nGiven this history to start:\n\n             B\n              \\\n           A---C---D\n\nAlso given that we're specifying a commit-filter but *not* a parent- \nfilter.\n\nWhen that commit-filter is given A and B, it returns A' and B' without  \ndoing any changes (A' and B' in this case come from git-commit-tree).  \nWhen given C, the commit-filter returns A. When given D, it returns D'  \nagain with no changes.\n\nThe resulting history will look like this:\n\n            B'\n\n          A'   A---D'\n\nAs you can see, there is no C' commit (as the commit-filter simply  \nreturned A), and the A' and B' commits are left dangling.\n\nHere is a shell script which will generate this exact repo:\n\nhttp://pastie.textmate.org/206265\n\nIf you inspect the result, you'll see HEAD points to D' with a parent  \nof A, and that there are two dangling commits A' and B'.\n\nWhat I was talking about with the map can be demonstrated here. If you  \nedit the commit-filter to print out some debug info while writing D',  \nyou can see that $(map $(git rev-parse C)) will output $(git rev-parse  \nA).\n\n-Kevin\n\n-- \nKevin Ballard\nhttp://kevin.sb.org\nkevin@sb.org\nhttp://www.tildesoft.com\n"},{"id":"78204","messageId":"7v1w3jgs51.fsf@gitster.siamese.dyndns.org","threadId":"13737","inReplyTo":"AF9CB160-FFC9-4372-BE86-5FAC6B59A050@sb.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-31T01:48:58Z","receivedAt":"2008-05-31T01:48:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kevin Ballard <kevin@sb.org> writes:\n\n> You're still talking about the parent-filter here. I think you're\n> quite confused.\n\nBlush.  I should go to bed.\n"},{"id":"78251","messageId":"7vskvydrys.fsf@gitster.siamese.dyndns.org","threadId":"13737","inReplyTo":"7v1w3jgs51.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-31T22:33:15Z","receivedAt":"2008-05-31T22:33:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Kevin Ballard <kevin@sb.org> writes:\n>\n>> You're still talking about the parent-filter here. I think you're\n>> quite confused.\n>\n> Blush.  I should go to bed.\n\nNow after following the codepath, your original\n\n    diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\n    index 506c37a..541bf23 100644\n    --- a/Documentation/git-filter-branch.txt\n    +++ b/Documentation/git-filter-branch.txt\n    @@ -113,8 +113,8 @@ OPTIONS\n            stdin.  The commit id is expected on stdout.\n     +\n     As a special extension, the commit filter may emit multiple\n    -commit ids; in that case, ancestors of the original commit will\n    -have all of them as parents.\n    +commit ids; in that case, the rewritten children of the original commit will\n    +have all of them as parents. You probably don't want to do this.\n     +\n     You can use the 'map' convenience function in this filter, and other\n     convenience functions, too.  For example, calling 'skip_commit \"$@\"'\n\ndoes make sense to me.  Except for \"You probably don't want to do this.\"\npart.  It is just \"the utility of this feature is unknown to us\" ;-)\n\nI dug the code with \"git blame\" and the basic logic has been the same\nsince its introduction to git with 6f6826c (Add git-filter-branch,\n2007-06-03).  The commit-filter itself appeared first in Cogito as d690516\n(cg-admin-rewritehist --commit-filter for omitting commits, 2006-03-26),\nand the commit log message claims that it was primarily meant to _omit_\nunwanted commits from the history, but at the same time it advertises the\nmultiple commits case as a \"feature\" without telling why somebody wants to\ndo so.\n\nExcept for this gem, which may have been lost in our copy:\n\n    # ... Note that this handles merges properly! In case Darl\n    # committed a merge between P1 and P2, it will be propagated properly\n    # and all children of the merge will become merge commits with P1,P2\n    # as their parents instead of the merge commit.\n\nIOW, to rewrite this history:\n\n        ---A---C---D---E\n              /\n             B \n\nto pretend C never happened, you would give A' and B' back when you\nrewrite C, to end up with this history:\n\n        ---A'--D'--E'\n              /\n             B' \n\nI'd agree with \"You probably don't want to do this\", but perhaps it needs\na bit of clarification as to _why_ you would not:\n\n - If the history is being rewritten for the whole tree, this will\n   make D' an evil merge that contains difference between C to D.\n\n - If the filtering of the history is done to ignore parts of the tree\n   that is touched between C and D (iow, history simplification would\n   leave trees C and D the same), you would want to simplify away D' not\n   C'.  IOW, you would want the resulting history to look like:\n\n        ---A'--C'--E'\n              /\n             B' \n\n   and for that you do not need to use this \"feature\".\n"},{"id":"78258","messageId":"CEA5A26A-9109-4D22-9D3F-8FFF8305DBEE@sb.org","threadId":"13737","inReplyTo":"7vskvydrys.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Documentation/git-filter-branch.txt: Fix description of --commit-filter","fromName":"Kevin Ballard","fromEmail":"kevin@sb.org","sentAt":"2008-05-31T23:50:00Z","receivedAt":"2008-05-31T23:50:00Z","isPatch":true,"sender":{"key":"kevin@sb.org","avatar":"https://avatars.githubusercontent.com/u/714?v=4"},"body":"On May 31, 2008, at 3:33 PM, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> Kevin Ballard <kevin@sb.org> writes:\n>>\n>>> You're still talking about the parent-filter here. I think you're\n>>> quite confused.\n>>\n>> Blush.  I should go to bed.\n>\n> Now after following the codepath, your original\n>\n>    diff --git a/Documentation/git-filter-branch.txt b/Documentation/ \n> git-filter-branch.txt\n>    index 506c37a..541bf23 100644\n>    --- a/Documentation/git-filter-branch.txt\n>    +++ b/Documentation/git-filter-branch.txt\n>    @@ -113,8 +113,8 @@ OPTIONS\n>            stdin.  The commit id is expected on stdout.\n>     +\n>     As a special extension, the commit filter may emit multiple\n>    -commit ids; in that case, ancestors of the original commit will\n>    -have all of them as parents.\n>    +commit ids; in that case, the rewritten children of the original  \n> commit will\n>    +have all of them as parents. You probably don't want to do this.\n>     +\n>     You can use the 'map' convenience function in this filter, and  \n> other\n>     convenience functions, too.  For example, calling 'skip_commit  \n> \"$@\"'\n>\n> does make sense to me.  Except for \"You probably don't want to do  \n> this.\"\n> part.  It is just \"the utility of this feature is unknown to us\" ;-)\n>\n> I dug the code with \"git blame\" and the basic logic has been the same\n> since its introduction to git with 6f6826c (Add git-filter-branch,\n> 2007-06-03).  The commit-filter itself appeared first in Cogito as  \n> d690516\n> (cg-admin-rewritehist --commit-filter for omitting commits,  \n> 2006-03-26),\n> and the commit log message claims that it was primarily meant to  \n> _omit_\n> unwanted commits from the history, but at the same time it  \n> advertises the\n> multiple commits case as a \"feature\" without telling why somebody  \n> wants to\n> do so.\n>\n> Except for this gem, which may have been lost in our copy:\n>\n>    # ... Note that this handles merges properly! In case Darl\n>    # committed a merge between P1 and P2, it will be propagated  \n> properly\n>    # and all children of the merge will become merge commits with  \n> P1,P2\n>    # as their parents instead of the merge commit.\n>\n> IOW, to rewrite this history:\n>\n>        ---A---C---D---E\n>              /\n>             B\n>\n> to pretend C never happened, you would give A' and B' back when you\n> rewrite C, to end up with this history:\n>\n>        ---A'--D'--E'\n>              /\n>             B'\n>\n> I'd agree with \"You probably don't want to do this\", but perhaps it  \n> needs\n> a bit of clarification as to _why_ you would not:\n>\n> - If the history is being rewritten for the whole tree, this will\n>   make D' an evil merge that contains difference between C to D.\n>\n> - If the filtering of the history is done to ignore parts of the tree\n>   that is touched between C and D (iow, history simplification would\n>   leave trees C and D the same), you would want to simplify away D'  \n> not\n>   C'.  IOW, you would want the resulting history to look like:\n>\n>        ---A'--C'--E'\n>              /\n>             B'\n>\n>   and for that you do not need to use this \"feature\".\n\nYeah, this utility of omitting commits occurred to me last night after  \nI went to bed. It does seem pretty limited in use, but I guess someone  \nmight want to do it. For example, if C resolved merge conflicts  \nincorrectly and D fixed it, and then later somebody said \"why do I  \nhave two commits when I should just have one?\" and wanted to omit C  \nand leave D behind as the merge.\n\nI'll submit a new patch later that has better wording and perhaps a  \ndiagram or two.\n\n-Kevin Ballard\n\n-- \nKevin Ballard\nhttp://kevin.sb.org\nkevin@sb.org\nhttp://www.tildesoft.com\n"}]}