Documentation / git-filter-branch.txton commit diff-tree -r -t: include added/removed directories in the output (df533f3)
   1git-filter-branch(1)
   2====================
   3
   4NAME
   5----
   6git-filter-branch - Rewrite branches
   7
   8SYNOPSIS
   9--------
  10[verse]
  11'git filter-branch' [--env-filter <command>] [--tree-filter <command>]
  12        [--index-filter <command>] [--parent-filter <command>]
  13        [--msg-filter <command>] [--commit-filter <command>]
  14        [--tag-name-filter <command>] [--subdirectory-filter <directory>]
  15        [--original <namespace>] [-d <directory>] [-f | --force]
  16        [--] [<rev-list options>...]
  17
  18DESCRIPTION
  19-----------
  20Lets you rewrite git revision history by rewriting the branches mentioned
  21in the <rev-list options>, applying custom filters on each revision.
  22Those filters can modify each tree (e.g. removing a file or running
  23a perl rewrite on all files) or information about each commit.
  24Otherwise, all information (including original commit times or merge
  25information) will be preserved.
  26
  27The command will only rewrite the _positive_ refs mentioned in the
  28command line (e.g. if you pass 'a..b', only 'b' will be rewritten).
  29If you specify no filters, the commits will be recommitted without any
  30changes, which would normally have no effect.  Nevertheless, this may be
  31useful in the future for compensating for some git bugs or such,
  32therefore such a usage is permitted.
  33
  34*NOTE*: This command honors `.git/info/grafts`. If you have any grafts
  35defined, running this command will make them permanent.
  36
  37*WARNING*! The rewritten history will have different object names for all
  38the objects and will not converge with the original branch.  You will not
  39be able to easily push and distribute the rewritten branch on top of the
  40original branch.  Please do not use this command if you do not know the
  41full implications, and avoid using it anyway, if a simple single commit
  42would suffice to fix your problem.
  43
  44Always verify that the rewritten version is correct: The original refs,
  45if different from the rewritten ones, will be stored in the namespace
  46'refs/original/'.
  47
  48Note that since this operation is very I/O expensive, it might
  49be a good idea to redirect the temporary directory off-disk with the
  50'-d' option, e.g. on tmpfs.  Reportedly the speedup is very noticeable.
  51
  52
  53Filters
  54~~~~~~~
  55
  56The filters are applied in the order as listed below.  The <command>
  57argument is always evaluated in the shell context using the 'eval' command
  58(with the notable exception of the commit filter, for technical reasons).
  59Prior to that, the $GIT_COMMIT environment variable will be set to contain
  60the id of the commit being rewritten.  Also, GIT_AUTHOR_NAME,
  61GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,
  62and GIT_COMMITTER_DATE are set according to the current commit.  The values
  63of these variables after the filters have run, are used for the new commit.
  64If any evaluation of <command> returns a non-zero exit status, the whole
  65operation will be aborted.
  66
  67A 'map' function is available that takes an "original sha1 id" argument
  68and outputs a "rewritten sha1 id" if the commit has been already
  69rewritten, and "original sha1 id" otherwise; the 'map' function can
  70return several ids on separate lines if your commit filter emitted
  71multiple commits.
  72
  73
  74OPTIONS
  75-------
  76
  77--env-filter <command>::
  78        This filter may be used if you only need to modify the environment
  79        in which the commit will be performed.  Specifically, you might
  80        want to rewrite the author/committer name/email/time environment
  81        variables (see linkgit:git-commit[1] for details).  Do not forget
  82        to re-export the variables.
  83
  84--tree-filter <command>::
  85        This is the filter for rewriting the tree and its contents.
  86        The argument is evaluated in shell with the working
  87        directory set to the root of the checked out tree.  The new tree
  88        is then used as-is (new files are auto-added, disappeared files
  89        are auto-removed - neither .gitignore files nor any other ignore
  90        rules *HAVE ANY EFFECT*!).
  91
  92--index-filter <command>::
  93        This is the filter for rewriting the index.  It is similar to the
  94        tree filter but does not check out the tree, which makes it much
  95        faster.  For hairy cases, see linkgit:git-update-index[1].
  96
  97--parent-filter <command>::
  98        This is the filter for rewriting the commit's parent list.
  99        It will receive the parent string on stdin and shall output
 100        the new parent string on stdout.  The parent string is in
 101        the format described in linkgit:git-commit-tree[1]: empty for
 102        the initial commit, "-p parent" for a normal commit and
 103        "-p parent1 -p parent2 -p parent3 ..." for a merge commit.
 104
 105--msg-filter <command>::
 106        This is the filter for rewriting the commit messages.
 107        The argument is evaluated in the shell with the original
 108        commit message on standard input; its standard output is
 109        used as the new commit message.
 110
 111--commit-filter <command>::
 112        This is the filter for performing the commit.
 113        If this filter is specified, it will be called instead of the
 114        'git-commit-tree' command, with arguments of the form
 115        "<TREE_ID> [-p <PARENT_COMMIT_ID>]..." and the log message on
 116        stdin.  The commit id is expected on stdout.
 117+
 118As a special extension, the commit filter may emit multiple
 119commit ids; in that case, the rewritten children of the original commit will
 120have all of them as parents.
 121+
 122You can use the 'map' convenience function in this filter, and other
 123convenience functions, too.  For example, calling 'skip_commit "$@"'
 124will leave out the current commit (but not its changes! If you want
 125that, use 'git-rebase' instead).
 126
 127--tag-name-filter <command>::
 128        This is the filter for rewriting tag names. When passed,
 129        it will be called for every tag ref that points to a rewritten
 130        object (or to a tag object which points to a rewritten object).
 131        The original tag name is passed via standard input, and the new
 132        tag name is expected on standard output.
 133+
 134The original tags are not deleted, but can be overwritten;
 135use "--tag-name-filter cat" to simply update the tags.  In this
 136case, be very careful and make sure you have the old tags
 137backed up in case the conversion has run afoul.
 138+
 139Nearly proper rewriting of tag objects is supported. If the tag has
 140a message attached, a new tag object will be created with the same message,
 141author, and timestamp. If the tag has a signature attached, the
 142signature will be stripped. It is by definition impossible to preserve
 143signatures. The reason this is "nearly" proper, is because ideally if
 144the tag did not change (points to the same object, has the same name, etc.)
 145it should retain any signature. That is not the case, signatures will always
 146be removed, buyer beware. There is also no support for changing the
 147author or timestamp (or the tag message for that matter). Tags which point
 148to other tags will be rewritten to point to the underlying commit.
 149
 150--subdirectory-filter <directory>::
 151        Only look at the history which touches the given subdirectory.
 152        The result will contain that directory (and only that) as its
 153        project root.
 154
 155--original <namespace>::
 156        Use this option to set the namespace where the original commits
 157        will be stored. The default value is 'refs/original'.
 158
 159-d <directory>::
 160        Use this option to set the path to the temporary directory used for
 161        rewriting.  When applying a tree filter, the command needs to
 162        temporarily check out the tree to some directory, which may consume
 163        considerable space in case of large projects.  By default it
 164        does this in the '.git-rewrite/' directory but you can override
 165        that choice by this parameter.
 166
 167-f::
 168--force::
 169        'git-filter-branch' refuses to start with an existing temporary
 170        directory or when there are already refs starting with
 171        'refs/original/', unless forced.
 172
 173<rev-list options>...::
 174        Arguments for 'git-rev-list'.  All positive refs included by
 175        these options are rewritten.  You may also specify options
 176        such as '--all', but you must use '--' to separate them from
 177        the 'git-filter-branch' options.
 178
 179
 180Examples
 181--------
 182
 183Suppose you want to remove a file (containing confidential information
 184or copyright violation) from all commits:
 185
 186-------------------------------------------------------
 187git filter-branch --tree-filter 'rm filename' HEAD
 188-------------------------------------------------------
 189
 190However, if the file is absent from the tree of some commit,
 191a simple `rm filename` will fail for that tree and commit.
 192Thus you may instead want to use `rm -f filename` as the script.
 193
 194A significantly faster version:
 195
 196--------------------------------------------------------------------------
 197git filter-branch --index-filter 'git rm --cached filename' HEAD
 198--------------------------------------------------------------------------
 199
 200Now, you will get the rewritten history saved in HEAD.
 201
 202To rewrite the repository to look as if `foodir/` had been its project
 203root, and discard all other history:
 204
 205-------------------------------------------------------
 206git filter-branch --subdirectory-filter foodir -- --all
 207-------------------------------------------------------
 208
 209Thus you can, e.g., turn a library subdirectory into a repository of
 210its own.  Note the `\--` that separates 'filter-branch' options from
 211revision options, and the `\--all` to rewrite all branches and tags.
 212
 213To set a commit (which typically is at the tip of another
 214history) to be the parent of the current initial commit, in
 215order to paste the other history behind the current history:
 216
 217-------------------------------------------------------------------
 218git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD
 219-------------------------------------------------------------------
 220
 221(if the parent string is empty - which happens when we are dealing with
 222the initial commit - add graftcommit as a parent).  Note that this assumes
 223history with a single root (that is, no merge without common ancestors
 224happened).  If this is not the case, use:
 225
 226--------------------------------------------------------------------------
 227git filter-branch --parent-filter \
 228        'test $GIT_COMMIT = <commit-id> && echo "-p <graft-id>" || cat' HEAD
 229--------------------------------------------------------------------------
 230
 231or even simpler:
 232
 233-----------------------------------------------
 234echo "$commit-id $graft-id" >> .git/info/grafts
 235git filter-branch $graft-id..HEAD
 236-----------------------------------------------
 237
 238To remove commits authored by "Darl McBribe" from the history:
 239
 240------------------------------------------------------------------------------
 241git filter-branch --commit-filter '
 242        if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
 243        then
 244                skip_commit "$@";
 245        else
 246                git commit-tree "$@";
 247        fi' HEAD
 248------------------------------------------------------------------------------
 249
 250The function 'skip_commit' is defined as follows:
 251
 252--------------------------
 253skip_commit()
 254{
 255        shift;
 256        while [ -n "$1" ];
 257        do
 258                shift;
 259                map "$1";
 260                shift;
 261        done;
 262}
 263--------------------------
 264
 265The shift magic first throws away the tree id and then the -p
 266parameters.  Note that this handles merges properly! In case Darl
 267committed a merge between P1 and P2, it will be propagated properly
 268and all children of the merge will become merge commits with P1,P2
 269as their parents instead of the merge commit.
 270
 271You can rewrite the commit log messages using `--msg-filter`.  For
 272example, 'git-svn-id' strings in a repository created by 'git-svn' can
 273be removed this way:
 274
 275-------------------------------------------------------
 276git filter-branch --msg-filter '
 277        sed -e "/^git-svn-id:/d"
 278'
 279-------------------------------------------------------
 280
 281To restrict rewriting to only part of the history, specify a revision
 282range in addition to the new branch name.  The new branch name will
 283point to the top-most revision that a 'git-rev-list' of this range
 284will print.
 285
 286*NOTE* the changes introduced by the commits, and which are not reverted
 287by subsequent commits, will still be in the rewritten branch. If you want
 288to throw out _changes_ together with the commits, you should use the
 289interactive mode of 'git-rebase'.
 290
 291
 292Consider this history:
 293
 294------------------
 295     D--E--F--G--H
 296    /     /
 297A--B-----C
 298------------------
 299
 300To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:
 301
 302--------------------------------
 303git filter-branch ... C..H
 304--------------------------------
 305
 306To rewrite commits E,F,G,H, use one of these:
 307
 308----------------------------------------
 309git filter-branch ... C..H --not D
 310git filter-branch ... D..H --not C
 311----------------------------------------
 312
 313To move the whole tree into a subdirectory, or remove it from there:
 314
 315---------------------------------------------------------------
 316git filter-branch --index-filter \
 317        'git ls-files -s | sed "s-\t-&newsubdir/-" |
 318                GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
 319                        git update-index --index-info &&
 320         mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
 321---------------------------------------------------------------
 322
 323
 324Author
 325------
 326Written by Petr "Pasky" Baudis <pasky@suse.cz>,
 327and the git list <git@vger.kernel.org>
 328
 329Documentation
 330--------------
 331Documentation by Petr Baudis and the git list.
 332
 333GIT
 334---
 335Part of the linkgit:git[1] suite