{"thread":{"id":"3709","subject":"History rewriting swiss army knife","startedAt":"2006-03-24T14:08:31Z","lastAt":"2006-03-26T13:17:43Z","messageCount":3,"participants":["Petr Baudis","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"17871","messageId":"20060324140831.GY18185@pasky.or.cz","threadId":"3709","inReplyTo":null,"subject":"History rewriting swiss army knife","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-03-24T14:08:31Z","receivedAt":"2006-03-24T14:08:31Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"  Hi,\n\n  it is not very frequent, but sometimes you really want to rewrite your\nhistory - you need to get rid of a copyright violation or a file with\nconfidential information slipped through, or who knows what other good\nreason you might have. As long as you are aware of the implications of\nall the tree/commit ids getting different, why not.\n\n  It's never been so easy before - I've written cg-admin-rewritehist,\nwhich will execute your filters for each commit (which can rewrite the\ntree contents, just the tree itself through the index, committer/author\ninformation and commit message) while the script will obviously preserve\nall the other information like merges, author/committer information etc.\nThe script will place the rewritten history on a newly created branch.\n\n  If you are interested, you can also look at the script at\n\n\thttp://kernel.org/git/?p=cogito/cogito.git;a=blob;f=cg-admin-rewritehist\n\nbut it has few Cogito dependencies.\n\n  Have fun,\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nRight now I am having amnesia and deja-vu at the same time.  I think\nI have forgotten this before.\n"},{"id":"17893","messageId":"7vek0rzchc.fsf@assigned-by-dhcp.cox.net","threadId":"3709","inReplyTo":"20060324140831.GY18185@pasky.or.cz","subject":"Re: History rewriting swiss army knife","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-03-24T22:47:43Z","receivedAt":"2006-03-24T22:47:43Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n>   It's never been so easy before - I've written cg-admin-rewritehist,\n> which will execute your filters for each commit (which can rewrite the\n> tree contents, just the tree itself through the index, committer/author\n> information and commit message) while the script will obviously preserve\n> all the other information like merges, author/committer information etc.\n\nHmph.  The above description sounds like you are not allowing\nthe user's custom script to drop existing parent (or graft a new\none) while rewriting.  I have not looked at how you are\ninterfacing with user's custom script, but I sort-of expected\nyou to throw a commit at it from older to newer (i.e. topo-order\nin reverse), along with the names of already re-written commit\nobjects that are parents of taht commit, and have it build a\nrewritten commit and report its object name back to you.\n\nBut it sounds like a useful tool in certain situations -- I\nsounded mildly negative last night, but after you gave an\nexample of cleaning up a half-botched import, I changed my mind.\n"},{"id":"17990","messageId":"20060326131743.GK18185@pasky.or.cz","threadId":"3709","inReplyTo":"7vek0rzchc.fsf@assigned-by-dhcp.cox.net","subject":"Re: History rewriting swiss army knife","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-03-26T13:17:43Z","receivedAt":"2006-03-26T13:17:43Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Mar 24, 2006 at 11:47:43PM CET, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> Petr Baudis <pasky@suse.cz> writes:\n> \n> >   It's never been so easy before - I've written cg-admin-rewritehist,\n> > which will execute your filters for each commit (which can rewrite the\n> > tree contents, just the tree itself through the index, committer/author\n> > information and commit message) while the script will obviously preserve\n> > all the other information like merges, author/committer information etc.\n> \n> Hmph.  The above description sounds like you are not allowing\n> the user's custom script to drop existing parent (or graft a new\n> one) while rewriting.  I have not looked at how you are\n> interfacing with user's custom script, but I sort-of expected\n> you to throw a commit at it from older to newer (i.e. topo-order\n> in reverse), along with the names of already re-written commit\n> objects that are parents of taht commit, and have it build a\n> rewritten commit and report its object name back to you.\n\nThere are rather several \"filters\" (user scripts) which are called at\nvarious stages of the commit rewrite. In sum they are doing the same\nthing as the single user script would, but cg-admin-rewritehist will\nprepare some things to you so that everyone does not have to write the\ncommon stuff again and again.\n\nThe net flexibility loss was zero, except two things:\n\n* The parents list construction was hardcoded. Now I added a parent\n  filter which gets the parent string on stdin (including the -p bits,\n  but life's tough) and let it rewrite it (e.g. add stuff at the end).\n  So to \"etch a graft\":\n\n\tcg-admin-rewritehist --parent-filter sed\\ 's/^$/-p graftcommitid/' newbranch\n\n  assuming single-root history; but you have current commit id in\n  $GIT_COMMIT so you can go wild:\n\n\tcg-admin-rewritehist --parent-filter 'cat; [ \"$GIT_COMMIT\" = \"COMMIT\" ] && echo \"-p GRAFTCOMMIT\"' newbranch\n\n* A new commit would be always created. Sometimes you might want to\n  omit some commits. Now I added a commit filter which would be\n  called instead of the git-commit-tree command.\n\n  To remove commits authored by \"Darl McBribe\" from the history:\n\n\tcg-admin-rewritehist --commit-filter '\n\t\tif [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ]; then\n\t\t\tshift\n\t\t\twhile [ -n \"$1\" ]; do\n\t\t\t\tshift; echo \"$1\"; shift\n\t\t\tdone\n\t\telse\n\t\t\tgit-commit-tree \"$@\"\n\t\tfi' newbranch\n\n  (note that this will handle even Darl's merges).\n\nThanks for the inspiration,\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nRight now I am having amnesia and deja-vu at the same time.  I think\nI have forgotten this before.\n"}]}