{"thread":{"id":"8838","subject":"[PATCH] Document git-filter-branch","startedAt":"2007-07-03T16:47:44Z","lastAt":"2007-07-11T17:03:02Z","messageCount":12,"participants":["Johannes Schindelin","Frank Lichtenheld","Johannes Sixt","Junio C Hamano","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"46388","messageId":"Pine.LNX.4.64.0707031746400.4071@racer.site","threadId":"8838","inReplyTo":null,"subject":"[PATCH] Document git-filter-branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-03T16:47:44Z","receivedAt":"2007-07-03T16:47:44Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis moves the documentation in git-filter-branch.sh to its own\nman page, with a few touch ups.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tSorry, for being so late. I just realised this is not yet in \n\tgit.git, and it would be better IMHO to have it in 1.5.3...\n\n Documentation/cmd-list.perl         |    1 +\n Documentation/git-filter-branch.txt |  261 +++++++++++++++++++++++++++++++++++\n git-filter-branch.sh                |  187 +------------------------\n 3 files changed, 265 insertions(+), 184 deletions(-)\n create mode 100644 Documentation/git-filter-branch.txt\n\ndiff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl\nindex f50f613..2143995 100755\n--- a/Documentation/cmd-list.perl\n+++ b/Documentation/cmd-list.perl\n@@ -105,6 +105,7 @@ git-diff-tree                           plumbinginterrogators\n git-fast-import\t\t\t\tancillarymanipulators\n git-fetch                               mainporcelain\n git-fetch-pack                          synchingrepositories\n+git-filter-branch                       ancillarymanipulators\n git-fmt-merge-msg                       purehelpers\n git-for-each-ref                        plumbinginterrogators\n git-format-patch                        mainporcelain\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nnew file mode 100644\nindex 0000000..ee60a1a\n--- /dev/null\n+++ b/Documentation/git-filter-branch.txt\n@@ -0,0 +1,261 @@\n+git-filter-branch(1)\n+====================\n+\n+NAME\n+----\n+git-filter-branch - Rewrite branches\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git-filter-branch' [--env-filter <command>] [--tree-filter <command>]\n+\t[--index-filter <command>] [--parent-filter <command>]\n+\t[--msg-filter <command>] [--commit-filter <command>]\n+\t[--tag-name-filter <command>] [--subdirectory-filter <directory>]\n+\t[-d <directory>] <new-branch-name> [<rev-list options>...]\n+\n+DESCRIPTION\n+-----------\n+Lets you rewrite git revision history by creating a new branch from\n+your current branch, applying custom filters on each revision.\n+Those filters can modify each tree (e.g. removing a file or running\n+a perl rewrite on all files) or information about each commit.\n+Otherwise, all information (including original commit times or merge\n+information) will be preserved.\n+\n+The command takes the new branch name as a mandatory argument and\n+the filters as optional arguments.  If you specify no filters, the\n+commits will be recommitted without any changes, which would normally\n+have no effect and result in the new branch pointing to the same\n+branch as your current branch.  Nevertheless, this may be useful in\n+the future for compensating for some git bugs or such, therefore\n+such a usage is permitted.\n+\n+WARNING! The rewritten history will have different object names for all\n+the objects and will not converge with the original branch.  You will not\n+be able to easily push and distribute the rewritten branch on top of the\n+original branch.  Please do not use this command if you do not know the\n+full implications, and avoid using it anyway, if a simple single commit\n+would suffice to fix your problem.\n+\n+Always verify that the rewritten version is correct before disposing\n+the original branch.\n+\n+Note that since this operation is extensively I/O expensive, it might\n+be a good idea to redirect the temporary directory it off-disk, e.g. on\n+tmpfs.  Reportedly the speedup is very noticeable.\n+\n+\n+Filters\n+~~~~~~~\n+\n+The filters are applied in the order as listed below.  The <command>\n+argument is always evaluated in shell using the 'eval' command.\n+The $GIT_COMMIT environment variable is permanently set to contain\n+the id of the commit being rewritten.  The author/committer environment\n+variables are set before the first filter is run.\n+\n+A 'map' function is available that takes an \"original sha1 id\" argument\n+and outputs a \"rewritten sha1 id\" if the commit has been already\n+rewritten, fails otherwise; the 'map' function can return several\n+ids on separate lines if your commit filter emitted multiple commits.\n+\n+\n+OPTIONS\n+-------\n+\n+--env-filter <command>::\n+\tThis is the filter for modifying the environment in which\n+\tthe commit will be performed.  Specifically, you might want\n+\tto rewrite the author/committer name/email/time environment\n+\tvariables (see gitlink:git-commit[1] for details).  Do not forget\n+\tto re-export the variables.\n+\n+--tree-filter <command>::\n+\tThis is the filter for rewriting the tree and its contents.\n+\tThe argument is evaluated in shell with the working\n+\tdirectory set to the root of the checked out tree.  The new tree\n+\tis then used as-is (new files are auto-added, disappeared files\n+\tare auto-removed - .gitignore files nor any other ignore rules\n+\tHAVE NO EFFECT!).\n+\n+--index-filter <command>::\n+\tThis is the filter for rewriting the index.  It is similar to the\n+\ttree filter but does not check out the tree, which makes it much\n+\tfaster.  For hairy cases, see gitlink:git-update-index[1].\n+\n+--parent-filter <command>::\n+\tThis is the filter for rewriting the commit's parent list.\n+\tIt will receive the parent string on stdin and shall output\n+\tthe new parent string on stdout.  The parent string is in\n+\ta format accepted by gitlink:git-commit-tree[1]: empty for\n+\tthe initial commit, \"-p parent\" for a normal commit and\n+\t\"-p parent1 -p parent2 -p parent3 ...\" for a merge commit.\n+\n+--msg-filter <command>::\n+\tThis is the filter for rewriting the commit messages.\n+\tThe argument is evaluated in the shell with the original\n+\tcommit message on standard input; its standard output is\n+\tused as the new commit message.\n+\n+--commit-filter <command>::\n+\tThis is the filter for performing the commit.\n+\tIf this filter is specified, it will be called instead of the\n+\tgitlink:git-commit-tree[1] command, with arguments of the form\n+\t\"<TREE_ID> [-p <PARENT_COMMIT_ID>]...\" and the log message on\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+\n+--tag-name-filter <command>::\n+\tThis is the filter for rewriting tag names. When passed,\n+\tit will be called for every tag ref that points to a rewritten\n+\tobject (or to a tag object which points to a rewritten object).\n+\tThe original tag name is passed via standard input, and the new\n+\ttag name is expected on standard output.\n++\n+The original tags are not deleted, but can be overwritten;\n+use \"--tag-name-filter=cat\" to simply update the tags.  In this\n+case, be very careful and make sure you have the old tags\n+backed up in case the conversion has run afoul.\n++\n+Note that there is currently no support for proper rewriting of\n+tag objects; in layman terms, if the tag has a message or signature\n+attached, the rewritten tag won't have it.  Sorry.  (It is by\n+definition impossible to preserve signatures at any rate.)\n+\n+--subdirectory-filter <directory>::\n+\tOnly regard the history, as seen by the given subdirectory.  The\n+\tresult will contain that directory as its project root.\n+\n+-d <directory>::\n+\tUse this option to set the path to the temporary directory used for\n+\trewriting.  When applying a tree filter, the command needs to\n+\ttemporary checkout the tree to some directory, which may consume\n+\tconsiderable space in case of large projects.  By default it\n+\tdoes this in the '.git-rewrite/' directory but you can override\n+\tthat choice by this parameter.\n+\n+<rev-list-options>::\n+\tWhen options are given after the new branch name, they will\n+\tbe passed to gitlink:git-rev-list[1].  Only commits in the resulting\n+\toutput will be filtered, although the filtered commits can still\n+\treference parents which are outside of that set.\n+\n+\n+Examples\n+--------\n+\n+Suppose you want to remove a file (containing confidential information\n+or copyright violation) from all commits:\n+\n+-------------------------------------------------------\n+git filter-branch --tree-filter 'rm filename' newbranch\n+-------------------------------------------------------\n+\n+A significantly faster version:\n+\n+-------------------------------------------------------------------------------\n+git filter-branch --index-filter 'git update-index --remove filename' newbranch\n+-------------------------------------------------------------------------------\n+\n+Now, you will get the rewritten history saved in the branch 'newbranch'\n+(your current branch is left untouched).\n+\n+To \"etch-graft\" a commit to the revision history (set a commit to be\n+the parent of the current initial commit and propagate that):\n+\n+----------------------------------------------------------------------\n+git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n+----------------------------------------------------------------------\n+\n+(if the parent string is empty - therefore we are dealing with the\n+initial commit - add graftcommit as a parent).  Note that this assumes\n+history with a single root (that is, no merge without common ancestors\n+happened).  If this is not the case, use:\n+\n+-------------------------------------------------------------------------------\n+git filter-branch --parent-filter \\\n+\t'cat; test $GIT_COMMIT = <commit-id> && echo \"-p <graft-id>\"' newbranch\n+-------------------------------------------------------------------------------\n+\n+To remove commits authored by \"Darl McBribe\" from the history:\n+\n+------------------------------------------------------------------------------\n+git filter-branch --commit-filter '\n+\tif [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ];\n+\tthen\n+\t\tshift;\n+\t\twhile [ -n \"$1\" ];\n+\t\tdo\n+\t\t\tshift;\n+\t\t\techo \"$1\";\n+\t\t\tshift;\n+\t\tdone;\n+\telse\n+\t\tgit commit-tree \"$@\";\n+\tfi' newbranch\n+------------------------------------------------------------------------------\n+\n+The shift magic first throws away the tree id and then the -p\n+parameters.  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+\n+To restrict rewriting to only part of the history, specify a revision\n+range in addition to the new branch name.  The new branch name will\n+point to the top-most revision that a 'git rev-list' of this range\n+will print.\n+\n+Note that the changes introduced by the commits, and not reverted by\n+subsequent commits, will still be in the rewritten branch. If you want\n+to throw out _changes_ together with the commits, you should use the\n+interactive mode of gitlink:git-rebase[1].\n+\n+Consider this history:\n+\n+------------------\n+     D--E--F--G--H\n+    /     /\n+A--B-----C\n+------------------\n+\n+To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:\n+\n+--------------------------------\n+git filter-branch ... new-H C..H\n+--------------------------------\n+\n+To rewrite commits E,F,G,H, use one of these:\n+\n+----------------------------------------\n+git filter-branch ... new-H C..H --not D\n+git filter-branch ... new-H D..H --not C\n+----------------------------------------\n+\n+To move the whole tree into a subdirectory, or remove it from there:\n+\n+---------------------------------------------------------------\n+git filter-branch --index-filter \\\n+\t'git ls-files -s | sed \"s-\\t-&newsubdir/-\" |\n+\t\tGIT_INDEX_FILE=$GIT_INDEX_FILE.new \\\n+\t\t\tgit update-index --index-info &&\n+\t mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' directorymoved\n+---------------------------------------------------------------\n+\n+\n+Author\n+------\n+Written by Petr \"Pasky\" Baudis <pasky@suse.cz>,\n+and the git list <git@vger.kernel.org>\n+\n+Documentation\n+--------------\n+Documentation by Petr Baudis and the git list.\n+\n+GIT\n+---\n+Part of the gitlink:git[7] suite\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 3772951..22fb5bf 100644\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -4,190 +4,9 @@\n # Copyright (c) Petr Baudis, 2006\n # Minimal changes to \"port\" it to core-git (c) Johannes Schindelin, 2007\n #\n-# Lets you rewrite GIT revision history by creating a new branch from\n-# your current branch by applying custom filters on each revision.\n-# Those filters can modify each tree (e.g. removing a file or running\n-# a perl rewrite on all files) or information about each commit.\n-# Otherwise, all information (including original commit times or merge\n-# information) will be preserved.\n-#\n-# The command takes the new branch name as a mandatory argument and\n-# the filters as optional arguments. If you specify no filters, the\n-# commits will be recommitted without any changes, which would normally\n-# have no effect and result with the new branch pointing to the same\n-# branch as your current branch. (Nevertheless, this may be useful in\n-# the future for compensating for some Git bugs or such, therefore\n-# such a usage is permitted.)\n-#\n-# WARNING! The rewritten history will have different ids for all the\n-# objects and will not converge with the original branch. You will not\n-# be able to easily push and distribute the rewritten branch. Please do\n-# not use this command if you do not know the full implications, and\n-# avoid using it anyway - do not do what a simple single commit on top\n-# of the current version would fix.\n-#\n-# Always verify that the rewritten version is correct before disposing\n-# the original branch.\n-#\n-# Note that since this operation is extensively I/O expensive, it might\n-# be a good idea to do it off-disk, e.g. on tmpfs. Reportedly the speedup\n-# is very noticeable.\n-#\n-# OPTIONS\n-# -------\n-# -d TEMPDIR:: The path to the temporary tree used for rewriting\n-#\tWhen applying a tree filter, the command needs to temporary\n-#\tcheckout the tree to some directory, which may consume\n-#\tconsiderable space in case of large projects. By default it\n-#\tdoes this in the '.git-rewrite/' directory but you can override\n-#\tthat choice by this parameter.\n-#\n-# Filters\n-# ~~~~~~~\n-# The filters are applied in the order as listed below. The COMMAND\n-# argument is always evaluated in shell using the 'eval' command.\n-# The $GIT_COMMIT environment variable is permanently set to contain\n-# the id of the commit being rewritten. The author/committer environment\n-# variables are set before the first filter is run.\n-#\n-# A 'map' function is available that takes an \"original sha1 id\" argument\n-# and outputs a \"rewritten sha1 id\" if the commit has been already\n-# rewritten, fails otherwise; the 'map' function can return several\n-# ids on separate lines if your commit filter emitted multiple commits\n-# (see below).\n-#\n-# --env-filter COMMAND:: The filter for modifying environment\n-#\tThis is the filter for modifying the environment in which\n-#\tthe commit will be performed. Specifically, you might want\n-#\tto rewrite the author/committer name/email/time environment\n-#\tvariables (see `git-commit` for details). Do not forget to\n-#\tre-export the variables.\n-#\n-# --tree-filter COMMAND:: The filter for rewriting tree (and its contents)\n-#\tThis is the filter for rewriting the tree and its contents.\n-#\tThe COMMAND argument is evaluated in shell with the working\n-#\tdirectory set to the root of the checked out tree. The new tree\n-#\tis then used as-is (new files are auto-added, disappeared files\n-#\tare auto-removed - .gitignore files nor any other ignore rules\n-#\tHAVE NO EFFECT!).\n-#\n-# --index-filter COMMAND:: The filter for rewriting index\n-#\tThis is the filter for rewriting the Git's directory index.\n-#\tIt is similar to the tree filter but does not check out the\n-#\ttree, which makes it much faster. However, you must use the\n-#\tlowlevel Git index manipulation commands to do your work.\n-#\n-# --parent-filter COMMAND:: The filter for rewriting parents\n-#\tThis is the filter for rewriting the commit's parent list.\n-#\tIt will receive the parent string on stdin and shall output\n-#\tthe new parent string on stdout. The parent string is in\n-#\tformat accepted by `git commit-tree`: empty for initial\n-#\tcommit, \"-p parent\" for a normal commit and \"-p parent1\n-#\t-p parent2 -p parent3 ...\" for a merge commit.\n-#\n-# --msg-filter COMMAND:: The filter for rewriting commit message\n-#\tThis is the filter for rewriting the commit messages.\n-#\tThe COMMAND argument is evaluated in shell with the original\n-#\tcommit message on standard input; its standard output is\n-#\tis used as the new commit message.\n-#\n-# --commit-filter COMMAND:: The filter for performing the commit\n-#\tIf this filter is passed, it will be called instead of the\n-#\t`git commit-tree` command, with those arguments:\n-#\n-#\t\tTREE_ID [-p PARENT_COMMIT_ID]...\n-#\n-#\tand the log message on stdin. The commit id is expected on\n-#\tstdout. As a special extension, the commit filter may emit\n-#\tmultiple commit ids; in that case, all of them will be used\n-#\tas parents instead of the original commit in further commits.\n-#\n-# --tag-name-filter COMMAND:: The filter for rewriting tag names.\n-#\tIf this filter is passed, it will be called for every tag ref\n-#\tthat points to a rewritten object (or to a tag object which\n-#\tpoints to a rewritten object). The original tag name is passed\n-#\tvia standard input, and the new tag name is expected on standard\n-#\toutput.\n-#\n-#\tThe original tags are not deleted, but can be overwritten;\n-#\tuse \"--tag-name-filter=cat\" to simply update the tags. In this\n-#\tcase, be very careful and make sure you have the old tags\n-#\tbacked up in case the conversion has run afoul.\n-#\n-#\tNote that there is currently no support for proper rewriting of\n-#\ttag objects; in layman terms, if the tag has a message or signature\n-#\tattached, the rewritten tag won't have it. Sorry. (It is by\n-#\tdefinition impossible to preserve signatures at any rate, though.)\n-#\n-# --subdirectory-filter DIRECTORY:: Only regard the history, as seen by\n-#\tthe given subdirectory. The result will contain that directory as\n-#\tits project root.\n-#\n-# EXAMPLE USAGE\n-# -------------\n-# Suppose you want to remove a file (containing confidential information\n-# or copyright violation) from all commits:\n-#\n-#\tgit-filter-branch --tree-filter 'rm filename' newbranch\n-#\n-# A significantly faster version:\n-#\n-#\tgit-filter-branch --index-filter 'git update-index --remove filename' newbranch\n-#\n-# Now, you will get the rewritten history saved in the branch 'newbranch'\n-# (your current branch is left untouched).\n-#\n-# To \"etch-graft\" a commit to the revision history (set a commit to be\n-# the parent of the current initial commit and propagate that):\n-#\n-#\tgit-filter-branch --parent-filter sed\\ 's/^$/-p graftcommitid/' newbranch\n-#\n-# (if the parent string is empty - therefore we are dealing with the\n-# initial commit - add graftcommit as a parent). Note that this assumes\n-# history with a single root (that is, no git-merge without common ancestors\n-# happened). If this is not the case, use:\n-#\n-#\tgit-filter-branch --parent-filter 'cat; [ \"$GIT_COMMIT\" = \"COMMIT\" ] && echo \"-p GRAFTCOMMIT\"' newbranch\n-#\n-# To remove commits authored by \"Darl McBribe\" from the history:\n-#\n-#\tgit-filter-branch --commit-filter 'if [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ]; then shift; while [ -n \"$1\" ]; do shift; echo \"$1\"; shift; done; else git commit-tree \"$@\"; fi' newbranch\n-#\n-# (the shift magic first throws away the tree id and then the -p\n-# parameters). 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-#\n-# To restrict rewriting to only part of the history, specify a revision\n-# range in addition to the new branch name. The new branch name will\n-# point to the top-most revision that a 'git rev-list' of this range\n-# will print.\n-#\n-# Consider this history:\n-#\n-#\t     D--E--F--G--H\n-#\t    /     /\n-#\tA--B-----C\n-#\n-# To rewrite commits D,E,F,G,H, use:\n-#\n-#\tgit-filter-branch ... new-H C..H\n-#\n-# To rewrite commits E,F,G,H, use one of these:\n-#\n-#\tgit-filter-branch ... new-H C..H --not D\n-#\tgit-filter-branch ... new-H D..H --not C\n-#\n-# To move the whole tree into a subdirectory, or remove it from there:\n-#\n-# git-filter-branch --index-filter \\\n-#\t'git ls-files -s | sed \"s-\\t-&newsubdir/-\" |\n-#\t\tGIT_INDEX_FILE=$GIT_INDEX_FILE.new \\\n-#\t\t\tgit update-index --index-info &&\n-#\t mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' directorymoved\n-\n-# Testsuite: TODO\n+# Lets you rewrite the revision history of the current branch, creating\n+# a new branch. You can specify a number of filters to modify the commits,\n+# files and trees.\n \n set -e\n \n-- \n1.5.3.rc0.2637.g1dd84-dirty\n"},{"id":"46413","messageId":"20070703220540.GN12721@planck.djpig.de","threadId":"8838","inReplyTo":"Pine.LNX.4.64.0707031746400.4071@racer.site","subject":"Re: [PATCH] Document git-filter-branch","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2007-07-03T22:05:40Z","receivedAt":"2007-07-03T22:05:40Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"General note: All the stuff in all uppercase should probably also\nhave some asciidoc emphasis.\n\nOn Tue, Jul 03, 2007 at 05:47:44PM +0100, Johannes Schindelin wrote:\n> +DESCRIPTION\n> +-----------\n> +Lets you rewrite git revision history by creating a new branch from\n> +your current branch, applying custom filters on each revision.\n> +Those filters can modify each tree (e.g. removing a file or running\n> +a perl rewrite on all files) or information about each commit.\n> +Otherwise, all information (including original commit times or merge\n> +information) will be preserved.\n> +\n> +The command takes the new branch name as a mandatory argument and\n> +the filters as optional arguments.  If you specify no filters, the\n> +commits will be recommitted without any changes, which would normally\n> +have no effect and result in the new branch pointing to the same\n> +branch as your current branch.  Nevertheless, this may be useful in\n> +the future for compensating for some git bugs or such, therefore\n> +such a usage is permitted.\n> +\n> +WARNING! The rewritten history will have different object names for all\n> +the objects and will not converge with the original branch.  You will not\n> +be able to easily push and distribute the rewritten branch on top of the\n> +original branch.  Please do not use this command if you do not know the\n> +full implications, and avoid using it anyway, if a simple single commit\n> +would suffice to fix your problem.\n> +\n> +Always verify that the rewritten version is correct before disposing\n> +the original branch.\n> +\n> +Note that since this operation is extensively I/O expensive, it might\n> +be a good idea to redirect the temporary directory it off-disk, e.g. on\n                                                    ^^^^^^\nThe \"it\" probably doesn't belong there.\n\n> +tmpfs.  Reportedly the speedup is very noticeable.\n> +\n> +\n> +Filters\n> +~~~~~~~\n> +\n> +The filters are applied in the order as listed below.  The <command>\n> +argument is always evaluated in shell using the 'eval' command.\n> +The $GIT_COMMIT environment variable is permanently set to contain\n                                           ^^^^^^^^^^^\nI find the use of this word in this context odd and a little confusing.\nMaybe better \"always\" or \"each time\"?\n\n> +the id of the commit being rewritten.  The author/committer environment\n> +variables are set before the first filter is run.\n\nMaybe give the actual names of the environment variables here?\n\n> +A 'map' function is available that takes an \"original sha1 id\" argument\n> +and outputs a \"rewritten sha1 id\" if the commit has been already\n> +rewritten, fails otherwise; the 'map' function can return several\n> +ids on separate lines if your commit filter emitted multiple commits.\n> +\n> +\n> +OPTIONS\n> +-------\n> +\n> +--env-filter <command>::\n> +\tThis is the filter for modifying the environment in which\n> +\tthe commit will be performed.  Specifically, you might want\n> +\tto rewrite the author/committer name/email/time environment\n> +\tvariables (see gitlink:git-commit[1] for details).  Do not forget\n> +\tto re-export the variables.\n> +\n> +--tree-filter <command>::\n> +\tThis is the filter for rewriting the tree and its contents.\n> +\tThe argument is evaluated in shell with the working\n> +\tdirectory set to the root of the checked out tree.  The new tree\n> +\tis then used as-is (new files are auto-added, disappeared files\n> +\tare auto-removed - .gitignore files nor any other ignore rules\n> +\tHAVE NO EFFECT!).\n\nIs \"nor\" correct here? Not just \"or\"?\n\n[...]\n> +--subdirectory-filter <directory>::\n> +\tOnly regard the history, as seen by the given subdirectory. The\n                              ^^^\nDoes this comma belong there?\n\n> +\tresult will contain that directory as its project root.\n> +\n> +-d <directory>::\n> +\tUse this option to set the path to the temporary directory used for\n> +\trewriting.  When applying a tree filter, the command needs to\n> +\ttemporary checkout the tree to some directory, which may consume\n> +\tconsiderable space in case of large projects.  By default it\n> +\tdoes this in the '.git-rewrite/' directory but you can override\n> +\tthat choice by this parameter.\n> +\n> +<rev-list-options>::\n> +\tWhen options are given after the new branch name, they will\n> +\tbe passed to gitlink:git-rev-list[1].  Only commits in the resulting\n> +\toutput will be filtered, although the filtered commits can still\n> +\treference parents which are outside of that set.\n> +\n> +\n> +Examples\n> +--------\n> +\n> +Suppose you want to remove a file (containing confidential information\n> +or copyright violation) from all commits:\n> +\n> +-------------------------------------------------------\n> +git filter-branch --tree-filter 'rm filename' newbranch\n> +-------------------------------------------------------\n> +\n> +A significantly faster version:\n> +\n> +-------------------------------------------------------------------------------\n> +git filter-branch --index-filter 'git update-index --remove filename' newbranch\n> +-------------------------------------------------------------------------------\n\nEven if your code goes beyond 80 chars, the surrounding \"---\" doesn't\nhave to and makes it even harder to read when reading the original\nasciidoc text.\n\n> +\n> +Now, you will get the rewritten history saved in the branch 'newbranch'\n> +(your current branch is left untouched).\n> +\n> +To \"etch-graft\" a commit to the revision history (set a commit to be\n> +the parent of the current initial commit and propagate that):\n> +\n> +----------------------------------------------------------------------\n> +git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n> +----------------------------------------------------------------------\n\nWouldn't have 'sed s/^$/-p <graft-id>/' exactly the same effect, since\nthe quotes are interpreted by the original shell anyway and not the\nfilter shell? Just wondering why it uses such a complicated way to\nexpress it.\n\n> +(if the parent string is empty - therefore we are dealing with the\n> +initial commit - add graftcommit as a parent).  Note that this assumes\n> +history with a single root (that is, no merge without common ancestors\n> +happened).  If this is not the case, use:\n> +\n[...]\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"46422","messageId":"Pine.LNX.4.64.0707040004200.4071@racer.site","threadId":"8838","inReplyTo":"20070703220540.GN12721@planck.djpig.de","subject":"Re: [PATCH] Document git-filter-branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-03T23:17:05Z","receivedAt":"2007-07-03T23:17:05Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\n[if you comment on just a small portion of the text, could you please \nquote only that? Thank you]\n\nOn Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n\n> General note: All the stuff in all uppercase should probably also\n> have some asciidoc emphasis.\n\nI do not understand. I grepped through all the docs for uppercase words \nemphasized in any way, and could not find one.\n\n> On Tue, Jul 03, 2007 at 05:47:44PM +0100, Johannes Schindelin wrote:\n>\n> > +Note that since this operation is extensively I/O expensive, it might\n> > +be a good idea to redirect the temporary directory it off-disk, e.g. on\n>                                                     ^^^^^^\n> The \"it\" probably doesn't belong there.\n\nRight.\n\n> > +The filters are applied in the order as listed below.  The <command>\n> > +argument is always evaluated in shell using the 'eval' command.\n> > +The $GIT_COMMIT environment variable is permanently set to contain\n>                                            ^^^^^^^^^^^\n> I find the use of this word in this context odd and a little confusing.\n> Maybe better \"always\" or \"each time\"?\n\nHow about\n\n\tPrior to that, the $GIT_COMMIT environment variable will be set to \n\tcontain the id of the commit being rewritten.\n\n> > +the id of the commit being rewritten.  The author/committer environment\n> > +variables are set before the first filter is run.\n> \n> Maybe give the actual names of the environment variables here?\n\nIf you think so:\n\n\tAlso, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, \n\tGIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE is \n\tset according to the current commit.\n\n> > +\tis then used as-is (new files are auto-added, disappeared files\n> > +\tare auto-removed - .gitignore files nor any other ignore rules\n> > +\tHAVE NO EFFECT!).\n> \n> Is \"nor\" correct here? Not just \"or\"?\n\nDo you like\n\n\tneither .gitignore files nor any other ignore rules HAVE ANY \n\tEFFECT!\n\n> [...]\n> > +--subdirectory-filter <directory>::\n> > +\tOnly regard the history, as seen by the given subdirectory. The\n>                               ^^^\n> Does this comma belong there?\n\nThis is my bad English. What I meant was this:\n\n        Only ever look at the history, which touches the given \n\tsubdirectory.  The result will contain that directory as its \n\tproject root.\n\n> > +-------------------------------------------------------------------------------\n> > +git filter-branch --index-filter 'git update-index --remove filename' newbranch\n> > +-------------------------------------------------------------------------------\n> \n> Even if your code goes beyond 80 chars, the surrounding \"---\" doesn't\n> have to and makes it even harder to read when reading the original\n> asciidoc text.\n\nI personally read the .txt files, and use asciidoc only when I am forced \nto. So it makes a difference for me.\n\n> > +----------------------------------------------------------------------\n> > +git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n> > +----------------------------------------------------------------------\n> \n> Wouldn't have 'sed s/^$/-p <graft-id>/' exactly the same effect, since\n> the quotes are interpreted by the original shell anyway and not the\n> filter shell? Just wondering why it uses such a complicated way to\n> express it.\n\nProbably not. Since the shell would interpret \"s/^$/-p\" and \"<graft-id>/\" \nas two arguments to sed.\n\nBesides, like Pasky, I am used to quote the argument, and not the whole \nline, that's why the line is still there as it is.\n\nThanks,\nDscho\n"},{"id":"46424","messageId":"Pine.LNX.4.64.0707040041040.4071@racer.site","threadId":"8838","inReplyTo":"20070703220540.GN12721@planck.djpig.de","subject":"[PATCH] Document git-filter-branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-03T23:41:55Z","receivedAt":"2007-07-03T23:41:55Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis moves the documentation in git-filter-branch.sh to its own\nman page, with a few touch ups (incorporating comments by Frank\nLichtenheld).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tChanges as per my other reply to you. I kinda waited for the \n\temphasis hint, but I guess it's bed time in Germany.\n\n Documentation/cmd-list.perl         |    1 +\n Documentation/git-filter-branch.txt |  262 +++++++++++++++++++++++++++++++++++\n git-filter-branch.sh                |  187 +------------------------\n 3 files changed, 266 insertions(+), 184 deletions(-)\n create mode 100644 Documentation/git-filter-branch.txt\n\ndiff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl\nindex f50f613..2143995 100755\n--- a/Documentation/cmd-list.perl\n+++ b/Documentation/cmd-list.perl\n@@ -105,6 +105,7 @@ git-diff-tree                           plumbinginterrogators\n git-fast-import\t\t\t\tancillarymanipulators\n git-fetch                               mainporcelain\n git-fetch-pack                          synchingrepositories\n+git-filter-branch                       ancillarymanipulators\n git-fmt-merge-msg                       purehelpers\n git-for-each-ref                        plumbinginterrogators\n git-format-patch                        mainporcelain\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nnew file mode 100644\nindex 0000000..2074f31\n--- /dev/null\n+++ b/Documentation/git-filter-branch.txt\n@@ -0,0 +1,262 @@\n+git-filter-branch(1)\n+====================\n+\n+NAME\n+----\n+git-filter-branch - Rewrite branches\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git-filter-branch' [--env-filter <command>] [--tree-filter <command>]\n+\t[--index-filter <command>] [--parent-filter <command>]\n+\t[--msg-filter <command>] [--commit-filter <command>]\n+\t[--tag-name-filter <command>] [--subdirectory-filter <directory>]\n+\t[-d <directory>] <new-branch-name> [<rev-list options>...]\n+\n+DESCRIPTION\n+-----------\n+Lets you rewrite git revision history by creating a new branch from\n+your current branch, applying custom filters on each revision.\n+Those filters can modify each tree (e.g. removing a file or running\n+a perl rewrite on all files) or information about each commit.\n+Otherwise, all information (including original commit times or merge\n+information) will be preserved.\n+\n+The command takes the new branch name as a mandatory argument and\n+the filters as optional arguments.  If you specify no filters, the\n+commits will be recommitted without any changes, which would normally\n+have no effect and result in the new branch pointing to the same\n+branch as your current branch.  Nevertheless, this may be useful in\n+the future for compensating for some git bugs or such, therefore\n+such a usage is permitted.\n+\n+WARNING! The rewritten history will have different object names for all\n+the objects and will not converge with the original branch.  You will not\n+be able to easily push and distribute the rewritten branch on top of the\n+original branch.  Please do not use this command if you do not know the\n+full implications, and avoid using it anyway, if a simple single commit\n+would suffice to fix your problem.\n+\n+Always verify that the rewritten version is correct before disposing\n+the original branch.\n+\n+Note that since this operation is extensively I/O expensive, it might\n+be a good idea to redirect the temporary directory off-disk, e.g. on\n+tmpfs.  Reportedly the speedup is very noticeable.\n+\n+\n+Filters\n+~~~~~~~\n+\n+The filters are applied in the order as listed below.  The <command>\n+argument is always evaluated in shell using the 'eval' command.\n+Prior to that, the $GIT_COMMIT environment variable will be set to contain\n+the id of the commit being rewritten.  Also, GIT_AUTHOR_NAME,\n+GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,\n+and GIT_COMMITTER_DATE is set according to the current commit.\n+\n+A 'map' function is available that takes an \"original sha1 id\" argument\n+and outputs a \"rewritten sha1 id\" if the commit has been already\n+rewritten, fails otherwise; the 'map' function can return several\n+ids on separate lines if your commit filter emitted multiple commits.\n+\n+\n+OPTIONS\n+-------\n+\n+--env-filter <command>::\n+\tThis is the filter for modifying the environment in which\n+\tthe commit will be performed.  Specifically, you might want\n+\tto rewrite the author/committer name/email/time environment\n+\tvariables (see gitlink:git-commit[1] for details).  Do not forget\n+\tto re-export the variables.\n+\n+--tree-filter <command>::\n+\tThis is the filter for rewriting the tree and its contents.\n+\tThe argument is evaluated in shell with the working\n+\tdirectory set to the root of the checked out tree.  The new tree\n+\tis then used as-is (new files are auto-added, disappeared files\n+\tare auto-removed - neither .gitignore files nor any other ignore\n+\trules HAVE ANY EFFECT!).\n+\n+--index-filter <command>::\n+\tThis is the filter for rewriting the index.  It is similar to the\n+\ttree filter but does not check out the tree, which makes it much\n+\tfaster.  For hairy cases, see gitlink:git-update-index[1].\n+\n+--parent-filter <command>::\n+\tThis is the filter for rewriting the commit's parent list.\n+\tIt will receive the parent string on stdin and shall output\n+\tthe new parent string on stdout.  The parent string is in\n+\ta format accepted by gitlink:git-commit-tree[1]: empty for\n+\tthe initial commit, \"-p parent\" for a normal commit and\n+\t\"-p parent1 -p parent2 -p parent3 ...\" for a merge commit.\n+\n+--msg-filter <command>::\n+\tThis is the filter for rewriting the commit messages.\n+\tThe argument is evaluated in the shell with the original\n+\tcommit message on standard input; its standard output is\n+\tused as the new commit message.\n+\n+--commit-filter <command>::\n+\tThis is the filter for performing the commit.\n+\tIf this filter is specified, it will be called instead of the\n+\tgitlink:git-commit-tree[1] command, with arguments of the form\n+\t\"<TREE_ID> [-p <PARENT_COMMIT_ID>]...\" and the log message on\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+\n+--tag-name-filter <command>::\n+\tThis is the filter for rewriting tag names. When passed,\n+\tit will be called for every tag ref that points to a rewritten\n+\tobject (or to a tag object which points to a rewritten object).\n+\tThe original tag name is passed via standard input, and the new\n+\ttag name is expected on standard output.\n++\n+The original tags are not deleted, but can be overwritten;\n+use \"--tag-name-filter=cat\" to simply update the tags.  In this\n+case, be very careful and make sure you have the old tags\n+backed up in case the conversion has run afoul.\n++\n+Note that there is currently no support for proper rewriting of\n+tag objects; in layman terms, if the tag has a message or signature\n+attached, the rewritten tag won't have it.  Sorry.  (It is by\n+definition impossible to preserve signatures at any rate.)\n+\n+--subdirectory-filter <directory>::\n+\tOnly ever look at the history, which touches the given subdirectory.\n+\tThe result will contain that directory as its project root.\n+\n+-d <directory>::\n+\tUse this option to set the path to the temporary directory used for\n+\trewriting.  When applying a tree filter, the command needs to\n+\ttemporary checkout the tree to some directory, which may consume\n+\tconsiderable space in case of large projects.  By default it\n+\tdoes this in the '.git-rewrite/' directory but you can override\n+\tthat choice by this parameter.\n+\n+<rev-list-options>::\n+\tWhen options are given after the new branch name, they will\n+\tbe passed to gitlink:git-rev-list[1].  Only commits in the resulting\n+\toutput will be filtered, although the filtered commits can still\n+\treference parents which are outside of that set.\n+\n+\n+Examples\n+--------\n+\n+Suppose you want to remove a file (containing confidential information\n+or copyright violation) from all commits:\n+\n+-------------------------------------------------------\n+git filter-branch --tree-filter 'rm filename' newbranch\n+-------------------------------------------------------\n+\n+A significantly faster version:\n+\n+-------------------------------------------------------------------------------\n+git filter-branch --index-filter 'git update-index --remove filename' newbranch\n+-------------------------------------------------------------------------------\n+\n+Now, you will get the rewritten history saved in the branch 'newbranch'\n+(your current branch is left untouched).\n+\n+To \"etch-graft\" a commit to the revision history (set a commit to be\n+the parent of the current initial commit and propagate that):\n+\n+----------------------------------------------------------------------\n+git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n+----------------------------------------------------------------------\n+\n+(if the parent string is empty - therefore we are dealing with the\n+initial commit - add graftcommit as a parent).  Note that this assumes\n+history with a single root (that is, no merge without common ancestors\n+happened).  If this is not the case, use:\n+\n+-------------------------------------------------------------------------------\n+git filter-branch --parent-filter \\\n+\t'cat; test $GIT_COMMIT = <commit-id> && echo \"-p <graft-id>\"' newbranch\n+-------------------------------------------------------------------------------\n+\n+To remove commits authored by \"Darl McBribe\" from the history:\n+\n+------------------------------------------------------------------------------\n+git filter-branch --commit-filter '\n+\tif [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ];\n+\tthen\n+\t\tshift;\n+\t\twhile [ -n \"$1\" ];\n+\t\tdo\n+\t\t\tshift;\n+\t\t\techo \"$1\";\n+\t\t\tshift;\n+\t\tdone;\n+\telse\n+\t\tgit commit-tree \"$@\";\n+\tfi' newbranch\n+------------------------------------------------------------------------------\n+\n+The shift magic first throws away the tree id and then the -p\n+parameters.  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+\n+To restrict rewriting to only part of the history, specify a revision\n+range in addition to the new branch name.  The new branch name will\n+point to the top-most revision that a 'git rev-list' of this range\n+will print.\n+\n+Note that the changes introduced by the commits, and not reverted by\n+subsequent commits, will still be in the rewritten branch. If you want\n+to throw out _changes_ together with the commits, you should use the\n+interactive mode of gitlink:git-rebase[1].\n+\n+Consider this history:\n+\n+------------------\n+     D--E--F--G--H\n+    /     /\n+A--B-----C\n+------------------\n+\n+To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:\n+\n+--------------------------------\n+git filter-branch ... new-H C..H\n+--------------------------------\n+\n+To rewrite commits E,F,G,H, use one of these:\n+\n+----------------------------------------\n+git filter-branch ... new-H C..H --not D\n+git filter-branch ... new-H D..H --not C\n+----------------------------------------\n+\n+To move the whole tree into a subdirectory, or remove it from there:\n+\n+---------------------------------------------------------------\n+git filter-branch --index-filter \\\n+\t'git ls-files -s | sed \"s-\\t-&newsubdir/-\" |\n+\t\tGIT_INDEX_FILE=$GIT_INDEX_FILE.new \\\n+\t\t\tgit update-index --index-info &&\n+\t mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' directorymoved\n+---------------------------------------------------------------\n+\n+\n+Author\n+------\n+Written by Petr \"Pasky\" Baudis <pasky@suse.cz>,\n+and the git list <git@vger.kernel.org>\n+\n+Documentation\n+--------------\n+Documentation by Petr Baudis and the git list.\n+\n+GIT\n+---\n+Part of the gitlink:git[7] suite\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 3772951..22fb5bf 100644\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -4,190 +4,9 @@\n # Copyright (c) Petr Baudis, 2006\n # Minimal changes to \"port\" it to core-git (c) Johannes Schindelin, 2007\n #\n-# Lets you rewrite GIT revision history by creating a new branch from\n-# your current branch by applying custom filters on each revision.\n-# Those filters can modify each tree (e.g. removing a file or running\n-# a perl rewrite on all files) or information about each commit.\n-# Otherwise, all information (including original commit times or merge\n-# information) will be preserved.\n-#\n-# The command takes the new branch name as a mandatory argument and\n-# the filters as optional arguments. If you specify no filters, the\n-# commits will be recommitted without any changes, which would normally\n-# have no effect and result with the new branch pointing to the same\n-# branch as your current branch. (Nevertheless, this may be useful in\n-# the future for compensating for some Git bugs or such, therefore\n-# such a usage is permitted.)\n-#\n-# WARNING! The rewritten history will have different ids for all the\n-# objects and will not converge with the original branch. You will not\n-# be able to easily push and distribute the rewritten branch. Please do\n-# not use this command if you do not know the full implications, and\n-# avoid using it anyway - do not do what a simple single commit on top\n-# of the current version would fix.\n-#\n-# Always verify that the rewritten version is correct before disposing\n-# the original branch.\n-#\n-# Note that since this operation is extensively I/O expensive, it might\n-# be a good idea to do it off-disk, e.g. on tmpfs. Reportedly the speedup\n-# is very noticeable.\n-#\n-# OPTIONS\n-# -------\n-# -d TEMPDIR:: The path to the temporary tree used for rewriting\n-#\tWhen applying a tree filter, the command needs to temporary\n-#\tcheckout the tree to some directory, which may consume\n-#\tconsiderable space in case of large projects. By default it\n-#\tdoes this in the '.git-rewrite/' directory but you can override\n-#\tthat choice by this parameter.\n-#\n-# Filters\n-# ~~~~~~~\n-# The filters are applied in the order as listed below. The COMMAND\n-# argument is always evaluated in shell using the 'eval' command.\n-# The $GIT_COMMIT environment variable is permanently set to contain\n-# the id of the commit being rewritten. The author/committer environment\n-# variables are set before the first filter is run.\n-#\n-# A 'map' function is available that takes an \"original sha1 id\" argument\n-# and outputs a \"rewritten sha1 id\" if the commit has been already\n-# rewritten, fails otherwise; the 'map' function can return several\n-# ids on separate lines if your commit filter emitted multiple commits\n-# (see below).\n-#\n-# --env-filter COMMAND:: The filter for modifying environment\n-#\tThis is the filter for modifying the environment in which\n-#\tthe commit will be performed. Specifically, you might want\n-#\tto rewrite the author/committer name/email/time environment\n-#\tvariables (see `git-commit` for details). Do not forget to\n-#\tre-export the variables.\n-#\n-# --tree-filter COMMAND:: The filter for rewriting tree (and its contents)\n-#\tThis is the filter for rewriting the tree and its contents.\n-#\tThe COMMAND argument is evaluated in shell with the working\n-#\tdirectory set to the root of the checked out tree. The new tree\n-#\tis then used as-is (new files are auto-added, disappeared files\n-#\tare auto-removed - .gitignore files nor any other ignore rules\n-#\tHAVE NO EFFECT!).\n-#\n-# --index-filter COMMAND:: The filter for rewriting index\n-#\tThis is the filter for rewriting the Git's directory index.\n-#\tIt is similar to the tree filter but does not check out the\n-#\ttree, which makes it much faster. However, you must use the\n-#\tlowlevel Git index manipulation commands to do your work.\n-#\n-# --parent-filter COMMAND:: The filter for rewriting parents\n-#\tThis is the filter for rewriting the commit's parent list.\n-#\tIt will receive the parent string on stdin and shall output\n-#\tthe new parent string on stdout. The parent string is in\n-#\tformat accepted by `git commit-tree`: empty for initial\n-#\tcommit, \"-p parent\" for a normal commit and \"-p parent1\n-#\t-p parent2 -p parent3 ...\" for a merge commit.\n-#\n-# --msg-filter COMMAND:: The filter for rewriting commit message\n-#\tThis is the filter for rewriting the commit messages.\n-#\tThe COMMAND argument is evaluated in shell with the original\n-#\tcommit message on standard input; its standard output is\n-#\tis used as the new commit message.\n-#\n-# --commit-filter COMMAND:: The filter for performing the commit\n-#\tIf this filter is passed, it will be called instead of the\n-#\t`git commit-tree` command, with those arguments:\n-#\n-#\t\tTREE_ID [-p PARENT_COMMIT_ID]...\n-#\n-#\tand the log message on stdin. The commit id is expected on\n-#\tstdout. As a special extension, the commit filter may emit\n-#\tmultiple commit ids; in that case, all of them will be used\n-#\tas parents instead of the original commit in further commits.\n-#\n-# --tag-name-filter COMMAND:: The filter for rewriting tag names.\n-#\tIf this filter is passed, it will be called for every tag ref\n-#\tthat points to a rewritten object (or to a tag object which\n-#\tpoints to a rewritten object). The original tag name is passed\n-#\tvia standard input, and the new tag name is expected on standard\n-#\toutput.\n-#\n-#\tThe original tags are not deleted, but can be overwritten;\n-#\tuse \"--tag-name-filter=cat\" to simply update the tags. In this\n-#\tcase, be very careful and make sure you have the old tags\n-#\tbacked up in case the conversion has run afoul.\n-#\n-#\tNote that there is currently no support for proper rewriting of\n-#\ttag objects; in layman terms, if the tag has a message or signature\n-#\tattached, the rewritten tag won't have it. Sorry. (It is by\n-#\tdefinition impossible to preserve signatures at any rate, though.)\n-#\n-# --subdirectory-filter DIRECTORY:: Only regard the history, as seen by\n-#\tthe given subdirectory. The result will contain that directory as\n-#\tits project root.\n-#\n-# EXAMPLE USAGE\n-# -------------\n-# Suppose you want to remove a file (containing confidential information\n-# or copyright violation) from all commits:\n-#\n-#\tgit-filter-branch --tree-filter 'rm filename' newbranch\n-#\n-# A significantly faster version:\n-#\n-#\tgit-filter-branch --index-filter 'git update-index --remove filename' newbranch\n-#\n-# Now, you will get the rewritten history saved in the branch 'newbranch'\n-# (your current branch is left untouched).\n-#\n-# To \"etch-graft\" a commit to the revision history (set a commit to be\n-# the parent of the current initial commit and propagate that):\n-#\n-#\tgit-filter-branch --parent-filter sed\\ 's/^$/-p graftcommitid/' newbranch\n-#\n-# (if the parent string is empty - therefore we are dealing with the\n-# initial commit - add graftcommit as a parent). Note that this assumes\n-# history with a single root (that is, no git-merge without common ancestors\n-# happened). If this is not the case, use:\n-#\n-#\tgit-filter-branch --parent-filter 'cat; [ \"$GIT_COMMIT\" = \"COMMIT\" ] && echo \"-p GRAFTCOMMIT\"' newbranch\n-#\n-# To remove commits authored by \"Darl McBribe\" from the history:\n-#\n-#\tgit-filter-branch --commit-filter 'if [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ]; then shift; while [ -n \"$1\" ]; do shift; echo \"$1\"; shift; done; else git commit-tree \"$@\"; fi' newbranch\n-#\n-# (the shift magic first throws away the tree id and then the -p\n-# parameters). 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-#\n-# To restrict rewriting to only part of the history, specify a revision\n-# range in addition to the new branch name. The new branch name will\n-# point to the top-most revision that a 'git rev-list' of this range\n-# will print.\n-#\n-# Consider this history:\n-#\n-#\t     D--E--F--G--H\n-#\t    /     /\n-#\tA--B-----C\n-#\n-# To rewrite commits D,E,F,G,H, use:\n-#\n-#\tgit-filter-branch ... new-H C..H\n-#\n-# To rewrite commits E,F,G,H, use one of these:\n-#\n-#\tgit-filter-branch ... new-H C..H --not D\n-#\tgit-filter-branch ... new-H D..H --not C\n-#\n-# To move the whole tree into a subdirectory, or remove it from there:\n-#\n-# git-filter-branch --index-filter \\\n-#\t'git ls-files -s | sed \"s-\\t-&newsubdir/-\" |\n-#\t\tGIT_INDEX_FILE=$GIT_INDEX_FILE.new \\\n-#\t\t\tgit update-index --index-info &&\n-#\t mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' directorymoved\n-\n-# Testsuite: TODO\n+# Lets you rewrite the revision history of the current branch, creating\n+# a new branch. You can specify a number of filters to modify the commits,\n+# files and trees.\n \n set -e\n \n-- \n1.5.3.rc0.2640.g59df9-dirty\n"},{"id":"46446","messageId":"1183534367401-git-send-email-johannes.sixt@telecom.at","threadId":"8838","inReplyTo":"20070703220540.GN12721@planck.djpig.de","subject":"[PATCH] filter-branch documentation: some more touch-ups.","fromName":"Johannes Sixt","fromEmail":"johannes.sixt@telecom.at","sentAt":"2007-07-04T07:32:47Z","receivedAt":"2007-07-04T07:32:47Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"- The map function used to fail, but no longer does (since 3520e1e8687.)\n- Fix the \"edge-graft\" example.\n- Show the same using .git/info/grafts.\n\nSigned-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n---\n\nI think that \"edge-graft\" makes more sense than \"etch-graft\".\nNative speakers, please?\n\nI tried the example, and its quoting was incorrect. The reason is that\nthe shell removes the single quotes even if they are in the middle of\na word; so they didn't end up in the eval'd script and made sed barf.\n\n-- Hannes\n\n Documentation/git-filter-branch.txt |   20 ++++++++++++++------\n 1 files changed, 14 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nindex ee60a1a..528ccc8 100644\n--- a/Documentation/git-filter-branch.txt\n+++ b/Documentation/git-filter-branch.txt\n@@ -57,8 +57,9 @@ variables are set before the first filter is run.\n \n A 'map' function is available that takes an \"original sha1 id\" argument\n and outputs a \"rewritten sha1 id\" if the commit has been already\n-rewritten, fails otherwise; the 'map' function can return several\n-ids on separate lines if your commit filter emitted multiple commits.\n+rewritten, and \"original sha1 id\" otherwise; the 'map' function can\n+return several ids on separate lines if your commit filter emitted\n+multiple commits.\n \n \n OPTIONS\n@@ -164,12 +165,12 @@ git filter-branch --index-filter 'git update-index --remove filename' newbranch\n Now, you will get the rewritten history saved in the branch 'newbranch'\n (your current branch is left untouched).\n \n-To \"etch-graft\" a commit to the revision history (set a commit to be\n+To \"edge-graft\" a commit to the revision history (set a commit to be\n the parent of the current initial commit and propagate that):\n \n-----------------------------------------------------------------------\n-git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n-----------------------------------------------------------------------\n+------------------------------------------------------------------------\n+git filter-branch --parent-filter 'sed \"s/^\\$/-p <graft-id>/\"' newbranch\n+------------------------------------------------------------------------\n \n (if the parent string is empty - therefore we are dealing with the\n initial commit - add graftcommit as a parent).  Note that this assumes\n@@ -181,6 +182,13 @@ git filter-branch --parent-filter \\\n \t'cat; test $GIT_COMMIT = <commit-id> && echo \"-p <graft-id>\"' newbranch\n -------------------------------------------------------------------------------\n \n+or even simpler:\n+\n+-----------------------------------------------\n+echo \"$commit-id $graft-id\" >> .git/info/grafts\n+git filter-branch newbranch $graft-id..\n+-----------------------------------------------\n+\n To remove commits authored by \"Darl McBribe\" from the history:\n \n ------------------------------------------------------------------------------\n-- \n1.5.3.rc0.5.g7cd9\n"},{"id":"46464","messageId":"Pine.LNX.4.64.0707041155110.4071@racer.site","threadId":"8838","inReplyTo":"1183534367401-git-send-email-johannes.sixt@telecom.at","subject":"Re: [PATCH] filter-branch documentation: some more touch-ups.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-04T10:58:18Z","receivedAt":"2007-07-04T10:58:18Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 4 Jul 2007, Johannes Sixt wrote:\n\n> - The map function used to fail, but no longer does (since 3520e1e8687.)\n> - Fix the \"edge-graft\" example.\n> - Show the same using .git/info/grafts.\n> \n> Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n> ---\n> \n> I think that \"edge-graft\" makes more sense than \"etch-graft\".\n> Native speakers, please?\n\nI looked at dict.leo.org, and it does not know either version. Maybe it is \njust \"graft\"?\n\nExcept for that,\n\nAcked-by: Johannes E. Schindelin <johannes.schindelin@gmx.de>\n\n> I tried the example, and its quoting was incorrect. The reason is that\n> the shell removes the single quotes even if they are in the middle of\n> a word; so they didn't end up in the eval'd script and made sed barf.\n\nThanks for sanity checking. It looked so obviously correct to me that I \ndid not bother checking, but your are correct, they were broken. \nUnfortunately, I even would have missed it writing a test case, because \nthat need an extra level of quoting!\n\nCiao,\nDscho\n"},{"id":"46467","messageId":"20070704112900.GO12721@planck.djpig.de","threadId":"8838","inReplyTo":"Pine.LNX.4.64.0707040004200.4071@racer.site","subject":"Re: [PATCH] Document git-filter-branch","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2007-07-04T11:29:01Z","receivedAt":"2007-07-04T11:29:01Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"On Wed, Jul 04, 2007 at 12:17:05AM +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> [if you comment on just a small portion of the text, could you please \n> quote only that? Thank you]\n> \n> On Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n> \n> > General note: All the stuff in all uppercase should probably also\n> > have some asciidoc emphasis.\n> \n> I do not understand. I grepped through all the docs for uppercase words \n> emphasized in any way, and could not find one.\n\nTrue. On the other hand it is used at least in the case of WARNING as\na means of emphasis and this should be reflected in the end result\nas markup. So I still suggest changing it to *WARNING* or even\n*Warning* if you don't want to double the emphasis.\n\n> > On Tue, Jul 03, 2007 at 05:47:44PM +0100, Johannes Schindelin wrote:\n> > > +the id of the commit being rewritten.  The author/committer environment\n> > > +variables are set before the first filter is run.\n> > \n> > Maybe give the actual names of the environment variables here?\n> \n> If you think so:\n> \n> \tAlso, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, \n> \tGIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE is \n> \tset according to the current commit.\n\n\"are\" set. And yeah, it doesn't look pretty. I still prefer having the\nlist somewhere in the text, though.\n\n> > > +\tOnly regard the history, as seen by the given subdirectory. The\n> >                               ^^^\n> > Does this comma belong there?\n> \n> This is my bad English. What I meant was this:\n> \n>         Only ever look at the history, which touches the given \n> \tsubdirectory.  The result will contain that directory as its \n> \tproject root.\n\nI'm still not sure there should be a comma in this sentence, but my\nEnglish grammar is a bit rusty.\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"46490","messageId":"Pine.LNX.4.64.0707041546510.4071@racer.site","threadId":"8838","inReplyTo":"20070704112900.GO12721@planck.djpig.de","subject":"[PATCH] filter-branch: a few more touch ups to the man page","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-04T14:50:45Z","receivedAt":"2007-07-04T14:50:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nAll based on comments from Frank Lichtenheld.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\n\tOn Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n\n\t> On Wed, Jul 04, 2007 at 12:17:05AM +0100, Johannes Schindelin wrote:\n\t> > \n\t> > On Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n\t> > \n\t> > > General note: All the stuff in all uppercase should probably \n\t> > > also have some asciidoc emphasis.\n\t>\n\t> [...] it is used at least in the case of WARNING as a means of \n\t> emphasis and this should be reflected in the end result as \n\t> markup. So I still suggest changing it to *WARNING* or even \n\t> *Warning* if you don't want to double the emphasis.\n\t> \n\t> > Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, \n\t> > GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and \n\t> > GIT_COMMITTER_DATE is set according to the current commit.\n\t> \n\t> \"are\" set. And yeah, it doesn't look pretty. I still prefer \n\t> having the list somewhere in the text, though.\n\t> \n\t> > > > +      Only regard the history, as seen by the given [...]\n\t> > >                                ^^^\n\t> > > Does this comma belong there?\n\t> > \n\t> > This is my bad English. What I meant was this:\n\t> > \n\t> > Only ever look at the history, which touches the given\n\t> > subdirectory.  The result will contain that directory as its\n\t> > project root.\n\t> \n\t> I'm still not sure there should be a comma in this sentence, but \n\t> my English grammar is a bit rusty.\n\n\tBetter?\n\n Documentation/git-filter-branch.txt |   11 ++++++-----\n 1 files changed, 6 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nindex 2074f31..363287d 100644\n--- a/Documentation/git-filter-branch.txt\n+++ b/Documentation/git-filter-branch.txt\n@@ -31,7 +31,7 @@ branch as your current branch.  Nevertheless, this may be useful in\n the future for compensating for some git bugs or such, therefore\n such a usage is permitted.\n \n-WARNING! The rewritten history will have different object names for all\n+*WARNING*! The rewritten history will have different object names for all\n the objects and will not converge with the original branch.  You will not\n be able to easily push and distribute the rewritten branch on top of the\n original branch.  Please do not use this command if you do not know the\n@@ -54,7 +54,7 @@ argument is always evaluated in shell using the 'eval' command.\n Prior to that, the $GIT_COMMIT environment variable will be set to contain\n the id of the commit being rewritten.  Also, GIT_AUTHOR_NAME,\n GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,\n-and GIT_COMMITTER_DATE is set according to the current commit.\n+and GIT_COMMITTER_DATE are set according to the current commit.\n \n A 'map' function is available that takes an \"original sha1 id\" argument\n and outputs a \"rewritten sha1 id\" if the commit has been already\n@@ -78,7 +78,7 @@ OPTIONS\n \tdirectory set to the root of the checked out tree.  The new tree\n \tis then used as-is (new files are auto-added, disappeared files\n \tare auto-removed - neither .gitignore files nor any other ignore\n-\trules HAVE ANY EFFECT!).\n+\trules *HAVE ANY EFFECT*!).\n \n --index-filter <command>::\n \tThis is the filter for rewriting the index.  It is similar to the\n@@ -128,8 +128,9 @@ attached, the rewritten tag won't have it.  Sorry.  (It is by\n definition impossible to preserve signatures at any rate.)\n \n --subdirectory-filter <directory>::\n-\tOnly ever look at the history, which touches the given subdirectory.\n-\tThe result will contain that directory as its project root.\n+\tOnly look at the history which touches the given subdirectory.\n+\tThe result will contain that directory (and only that) as its\n+\tproject root.\n \n -d <directory>::\n \tUse this option to set the path to the temporary directory used for\n-- \n1.5.3.rc0.2663.gfbb70\n"},{"id":"46491","messageId":"20070704150614.GC24861@planck.djpig.de","threadId":"8838","inReplyTo":"Pine.LNX.4.64.0707041546510.4071@racer.site","subject":"Re: [PATCH] filter-branch: a few more touch ups to the man page","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2007-07-04T15:06:15Z","receivedAt":"2007-07-04T15:06:15Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"On Wed, Jul 04, 2007 at 03:50:45PM +0100, Johannes Schindelin wrote:\n> \n> All based on comments from Frank Lichtenheld.\n\nAcked-by: Frank Lichtenheld <frank@lichtenheld.de>\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"46495","messageId":"7vhcokhzu3.fsf@assigned-by-dhcp.cox.net","threadId":"8838","inReplyTo":"Pine.LNX.4.64.0707041155110.4071@racer.site","subject":"Re: [PATCH] filter-branch documentation: some more touch-ups.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-04T16:56:52Z","receivedAt":"2007-07-04T16:56:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Wed, 4 Jul 2007, Johannes Sixt wrote:\n>\n>> - The map function used to fail, but no longer does (since 3520e1e8687.)\n>> - Fix the \"edge-graft\" example.\n>> - Show the same using .git/info/grafts.\n>> \n>> Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>\n>> ---\n>> \n>> I think that \"edge-graft\" makes more sense than \"etch-graft\".\n>> Native speakers, please?\n>\n> I looked at dict.leo.org, and it does not know either version. Maybe it is \n> just \"graft\"?\n\nWhy even need a new term there, if you are not going to use it\nelsewhere?  Instead of saying:\n\n    -To \"etch-graft\" a commit to the revision history (set a commit to be\n    +To \"edge-graft\" a commit to the revision history (set a commit to be\n     the parent of the current initial commit and propagate that):\n\n     ----------------------------------------------------------------------\n     git filter-branch --parent-filter sed\\ 's/^$/-p <graft-id>/' newbranch\n     ----------------------------------------------------------------------\n\n\nYou could say:\n\n\tTo set a commit to be the parent of the current initial\n\tcommit and propagate that:\n\nwithout inventing unfamiliar word that is not used anywhere else\nin the documentation.\n\nOne thing that you may want to stress is that <graft-id> does\nnot represent a single commit, but the history that leads to it.\nSo \"set a commit to be a parent\" is technically correct, but it\nis not \"To edge-graft _a_ commit\", but more like \"Paste another\nhistory behind the current beginning of time\".\n\nYou have two filmstrips, the first frame of one filmstrip, your\ncurrent history, should logically follow the last frame of the\nother filmstrip but they are separated into two.  You are\nsplicing them together to make a single, longer, filmstrip.\n"},{"id":"47047","messageId":"f731u9$1ir$1@sea.gmane.org","threadId":"8838","inReplyTo":"Pine.LNX.4.64.0707040004200.4071@racer.site","subject":"Re: [PATCH] Document git-filter-branch","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-07-11T16:53:29Z","receivedAt":"2007-07-11T16:53:29Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"[Cc: git@vger.kernel.org, Johannes Schindelin <Johannes.Schindelin@gmx.de>,\n Frank Lichtenheld <frank@lichtenheld.de>]\n\nJohannes Schindelin wrote:\n> On Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n\n>>> +Note that since this operation is extensively I/O expensive, it might\n>>> +be a good idea to redirect the temporary directory it off-disk, e.g. on\n\nBy the way, could git-filter-branch use git-fast-import to reduce I/O?\n\n>>> +the id of the commit being rewritten.  The author/committer environment\n>>> +variables are set before the first filter is run.\n>> \n>> Maybe give the actual names of the environment variables here?\n> \n> If you think so:\n> \n>       Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, \n>       GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE is \n>       set according to the current commit.\n\nOr\n\n        Also, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, \n        GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL, and GIT_COMMITTER_DATE  \n        are filled with data taken from the current commit. \n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"47048","messageId":"Pine.LNX.4.64.0707111800230.4516@racer.site","threadId":"8838","inReplyTo":"f731u9$1ir$1@sea.gmane.org","subject":"Re: [PATCH] Document git-filter-branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T17:03:02Z","receivedAt":"2007-07-11T17:03:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 11 Jul 2007, Jakub Narebski wrote:\n\n> Johannes Schindelin wrote:\n> > On Wed, 4 Jul 2007, Frank Lichtenheld wrote:\n> \n> >>> +Note that since this operation is extensively I/O expensive, it might\n> >>> +be a good idea to redirect the temporary directory it off-disk, e.g. on\n> \n> By the way, could git-filter-branch use git-fast-import to reduce I/O?\n\nThat idea has been kicked around.  But since skimo promised that he works \non rewrite-commits, which will be much faster.  So I do not see any point \nin working on filter-branch any more.\n\nBTW good to see you back on the list!\n\nCiao,\nDscho\n"}]}