{"thread":{"id":"8511","subject":"[PATCH 2/2] filter-branch: subdirectory filter needs --full-history","startedAt":"2007-06-08T21:28:50Z","lastAt":"2007-06-13T06:58:53Z","messageCount":3,"participants":["Johannes Sixt","Linus Torvalds","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"44378","messageId":"200706082328.50923.johannes.sixt@telecom.at","threadId":"8511","inReplyTo":null,"subject":"[PATCH 2/2] filter-branch: subdirectory filter needs --full-history","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2007-06-08T21:28:50Z","receivedAt":"2007-06-08T21:28:50Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"When two branches are merged that modify a subdirectory (possibly in\ndifferent intermediate steps) such that both end up identical, then\nrev-list chooses only one branch. But when we filter history, we want to\nkeep both branches. Therefore, we must use --full-history.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n git-filter-branch.sh     |    2 +-\n t/t7003-filter-branch.sh |   21 +++++++++++++++++++++\n 2 files changed, 22 insertions(+), 1 deletions(-)\n\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 4ef4570..2e4ccec 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -326,7 +326,7 @@ case \"$filter_subdir\" in\n \t;;\n *)\n \tgit-rev-list --reverse --topo-order --default HEAD \\\n-\t\t--parents \"$@\" -- \"$filter_subdir\"\n+\t\t--parents --full-history \"$@\" -- \"$filter_subdir\"\n esac > ../revs\n commits=$(cat ../revs | wc -l | tr -d \" \")\n \ndiff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh\nindex 292b837..0fabe49 100755\n--- a/t/t7003-filter-branch.sh\n+++ b/t/t7003-filter-branch.sh\n@@ -78,4 +78,25 @@ test_expect_success 'subdirectory filter result looks \nokay' '\n \t! git show sub:subdir\n '\n \n+test_expect_success 'setup and filter history that requires --full-history' '\n+\tgit checkout master &&\n+\tmkdir subdir &&\n+\techo A > subdir/new &&\n+\tgit add subdir/new &&\n+\ttest_tick &&\n+\tgit commit -m \"subdir on master\" subdir/new &&\n+\tgit rm a &&\n+\ttest_tick &&\n+\tgit commit -m \"again subdir on master\" &&\n+\tgit merge branch &&\n+\tgit-filter-branch --subdirectory-filter subdir sub-master\n+'\n+\n+test_expect_success 'subdirectory filter result looks okay' '\n+\ttest 3 = $(git-rev-list -1 --parents sub-master | wc -w) &&\n+\tgit show sub-master^:new &&\n+\tgit show sub-master^2:new &&\n+\t! git show sub:subdir\n+'\n+\n test_done\n-- \n1.5.2\n"},{"id":"44427","messageId":"alpine.LFD.0.98.0706081822500.4205@woody.linux-foundation.org","threadId":"8511","inReplyTo":"200706082328.50923.johannes.sixt@telecom.at","subject":"Re: [PATCH 2/2] filter-branch: subdirectory filter needs --full-history","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-06-09T02:40:46Z","receivedAt":"2007-06-09T02:40:46Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 8 Jun 2007, Johannes Sixt wrote:\n>\n> When two branches are merged that modify a subdirectory (possibly in\n> different intermediate steps) such that both end up identical, then\n> rev-list chooses only one branch. But when we filter history, we want to\n> keep both branches. Therefore, we must use --full-history.\n\n--full-history needs to be fixed up for this, I think.\n\nIt leaves *too* many merges around, in particular, it leaves merges where \nboth parents end up (after simplification) being related to each other.\n\nAs an example, do this:\n\n\tmkdir hello\n\tcd hello/\n\tgit init\n\n\techo \"Initial state\" > file-A\n\techo \"Another initial state\" > file-B\n\tgit add file-A file-B\n\tgit commit -m \"Initial commit\"\n\n\techo \"Add a line\" >> file-A\n\techo \"Add another line\" >> file-B\n\tgit commit -a -m \"On master branch\"\n\n\tgit checkout -b another HEAD^\n\techo \"Add a line\" >> file-A\n\tgit commit -a -m \"On another branch\"\n\n\tgit checkout master\n\tgit merge another\n\nand then do\n\n\tgitk --full-history file-B\n\nand notice what happens.. There was no actual developmet on branch \n\"another\", so all the commits went away, but it left the merge (because \nthat's how --full-history works), which has now become pointless.\n\nSo you should do a \"merge cleanup\" phase after running --full-history.\n\n\t\t\tLinus\n"},{"id":"44894","messageId":"7vps40fihe.fsf@assigned-by-dhcp.pobox.com","threadId":"8511","inReplyTo":"alpine.LFD.0.98.0706081822500.4205@woody.linux-foundation.org","subject":"Re: [PATCH 2/2] filter-branch: subdirectory filter needs --full-history","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-06-13T06:58:53Z","receivedAt":"2007-06-13T06:58:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> ... There was no actual developmet on branch \n> \"another\", so all the commits went away, but it left the merge (because \n> that's how --full-history works), which has now become pointless.\n>\n> So you should do a \"merge cleanup\" phase after running --full-history.\n\nIn short, you will end up with something like this:\n\n             .---. (side branch)\n            /     \\\n\t---A---B---C (merge)\n\nThe \"merge clean-up\" would conceptually be a simple operation.\nWhenever you see a merge C, you look at its parents A and B, and\ncull the ones that are reachable from other parents.  You notice\nthat A is an ancestor of B, drop A from the parents of C, and\nsimplify the above down to:\n\n\t---A---B---C (not-a-merge)\n\nHowever, I suspect that this is impossible without making\n--full-history with \"merge clean-up\" imply \"limited\".\n\nIn the case of filter-branch, it needs to use topo-order in\norder to guarantee that all its parents commits have been\nrewritten before rewriting a commit, so the traversal is already\nlimited.  \n\nIt might be simpler for filter-branch to remove parents that are\nancestor of other parents (\"git show-branch --independent\" would\nwork well for this, I think), before feeding the list of mapped\nparents to the parent-filter.\n"}]}