Autogenerated HTML docs for v1.7.4.1-55-gdca3d
[git/jnareb-git.git] / git-filter-branch.html
blob61bc94a5c9a27d777a7523c450769b157426b6f5
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6 <meta name="generator" content="AsciiDoc 8.4.5" />
7 <title>git-filter-branch(1)</title>
8 <style type="text/css">
9 /* Debug borders */
10 p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
12 border: 1px solid red;
16 body {
17 margin: 1em 5% 1em 5%;
20 a {
21 color: blue;
22 text-decoration: underline;
24 a:visited {
25 color: fuchsia;
28 em {
29 font-style: italic;
30 color: navy;
33 strong {
34 font-weight: bold;
35 color: #083194;
38 tt {
39 color: navy;
42 h1, h2, h3, h4, h5, h6 {
43 color: #527bbd;
44 font-family: sans-serif;
45 margin-top: 1.2em;
46 margin-bottom: 0.5em;
47 line-height: 1.3;
50 h1, h2, h3 {
51 border-bottom: 2px solid silver;
53 h2 {
54 padding-top: 0.5em;
56 h3 {
57 float: left;
59 h3 + * {
60 clear: left;
63 div.sectionbody {
64 font-family: serif;
65 margin-left: 0;
68 hr {
69 border: 1px solid silver;
72 p {
73 margin-top: 0.5em;
74 margin-bottom: 0.5em;
77 ul, ol, li > p {
78 margin-top: 0;
81 pre {
82 padding: 0;
83 margin: 0;
86 span#author {
87 color: #527bbd;
88 font-family: sans-serif;
89 font-weight: bold;
90 font-size: 1.1em;
92 span#email {
94 span#revnumber, span#revdate, span#revremark {
95 font-family: sans-serif;
98 div#footer {
99 font-family: sans-serif;
100 font-size: small;
101 border-top: 2px solid silver;
102 padding-top: 0.5em;
103 margin-top: 4.0em;
105 div#footer-text {
106 float: left;
107 padding-bottom: 0.5em;
109 div#footer-badges {
110 float: right;
111 padding-bottom: 0.5em;
114 div#preamble {
115 margin-top: 1.5em;
116 margin-bottom: 1.5em;
118 div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
119 div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
120 div.admonitionblock {
121 margin-top: 1.5em;
122 margin-bottom: 1.5em;
124 div.admonitionblock {
125 margin-top: 2.5em;
126 margin-bottom: 2.5em;
129 div.content { /* Block element content. */
130 padding: 0;
133 /* Block element titles. */
134 div.title, caption.title {
135 color: #527bbd;
136 font-family: sans-serif;
137 font-weight: bold;
138 text-align: left;
139 margin-top: 1.0em;
140 margin-bottom: 0.5em;
142 div.title + * {
143 margin-top: 0;
146 td div.title:first-child {
147 margin-top: 0.0em;
149 div.content div.title:first-child {
150 margin-top: 0.0em;
152 div.content + div.title {
153 margin-top: 0.0em;
156 div.sidebarblock > div.content {
157 background: #ffffee;
158 border: 1px solid silver;
159 padding: 0.5em;
162 div.listingblock > div.content {
163 border: 1px solid silver;
164 background: #f4f4f4;
165 padding: 0.5em;
168 div.quoteblock {
169 padding-left: 2.0em;
170 margin-right: 10%;
172 div.quoteblock > div.attribution {
173 padding-top: 0.5em;
174 text-align: right;
177 div.verseblock {
178 padding-left: 2.0em;
179 margin-right: 10%;
181 div.verseblock > div.content {
182 white-space: pre;
184 div.verseblock > div.attribution {
185 padding-top: 0.75em;
186 text-align: left;
188 /* DEPRECATED: Pre version 8.2.7 verse style literal block. */
189 div.verseblock + div.attribution {
190 text-align: left;
193 div.admonitionblock .icon {
194 vertical-align: top;
195 font-size: 1.1em;
196 font-weight: bold;
197 text-decoration: underline;
198 color: #527bbd;
199 padding-right: 0.5em;
201 div.admonitionblock td.content {
202 padding-left: 0.5em;
203 border-left: 2px solid silver;
206 div.exampleblock > div.content {
207 border-left: 2px solid silver;
208 padding: 0.5em;
211 div.imageblock div.content { padding-left: 0; }
212 span.image img { border-style: none; }
213 a.image:visited { color: white; }
215 dl {
216 margin-top: 0.8em;
217 margin-bottom: 0.8em;
219 dt {
220 margin-top: 0.5em;
221 margin-bottom: 0;
222 font-style: normal;
223 color: navy;
225 dd > *:first-child {
226 margin-top: 0.1em;
229 ul, ol {
230 list-style-position: outside;
232 ol.arabic {
233 list-style-type: decimal;
235 ol.loweralpha {
236 list-style-type: lower-alpha;
238 ol.upperalpha {
239 list-style-type: upper-alpha;
241 ol.lowerroman {
242 list-style-type: lower-roman;
244 ol.upperroman {
245 list-style-type: upper-roman;
248 div.compact ul, div.compact ol,
249 div.compact p, div.compact p,
250 div.compact div, div.compact div {
251 margin-top: 0.1em;
252 margin-bottom: 0.1em;
255 div.tableblock > table {
256 border: 3px solid #527bbd;
258 thead {
259 font-family: sans-serif;
260 font-weight: bold;
262 tfoot {
263 font-weight: bold;
265 td > div.verse {
266 white-space: pre;
268 p.table {
269 margin-top: 0;
271 /* Because the table frame attribute is overriden by CSS in most browsers. */
272 div.tableblock > table[frame="void"] {
273 border-style: none;
275 div.tableblock > table[frame="hsides"] {
276 border-left-style: none;
277 border-right-style: none;
279 div.tableblock > table[frame="vsides"] {
280 border-top-style: none;
281 border-bottom-style: none;
285 div.hdlist {
286 margin-top: 0.8em;
287 margin-bottom: 0.8em;
289 div.hdlist tr {
290 padding-bottom: 15px;
292 dt.hdlist1.strong, td.hdlist1.strong {
293 font-weight: bold;
295 td.hdlist1 {
296 vertical-align: top;
297 font-style: normal;
298 padding-right: 0.8em;
299 color: navy;
301 td.hdlist2 {
302 vertical-align: top;
304 div.hdlist.compact tr {
305 margin: 0;
306 padding-bottom: 0;
309 .comment {
310 background: yellow;
313 @media print {
314 div#footer-badges { display: none; }
317 div#toctitle {
318 color: #527bbd;
319 font-family: sans-serif;
320 font-size: 1.1em;
321 font-weight: bold;
322 margin-top: 1.0em;
323 margin-bottom: 0.1em;
326 div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
327 margin-top: 0;
328 margin-bottom: 0;
330 div.toclevel2 {
331 margin-left: 2em;
332 font-size: 0.9em;
334 div.toclevel3 {
335 margin-left: 4em;
336 font-size: 0.9em;
338 div.toclevel4 {
339 margin-left: 6em;
340 font-size: 0.9em;
342 /* Overrides for manpage documents */
343 h1 {
344 padding-top: 0.5em;
345 padding-bottom: 0.5em;
346 border-top: 2px solid silver;
347 border-bottom: 2px solid silver;
349 h2 {
350 border-style: none;
352 div.sectionbody {
353 margin-left: 5%;
356 @media print {
357 div#toc { display: none; }
360 /* Workarounds for IE6's broken and incomplete CSS2. */
362 div.sidebar-content {
363 background: #ffffee;
364 border: 1px solid silver;
365 padding: 0.5em;
367 div.sidebar-title, div.image-title {
368 color: #527bbd;
369 font-family: sans-serif;
370 font-weight: bold;
371 margin-top: 0.0em;
372 margin-bottom: 0.5em;
375 div.listingblock div.content {
376 border: 1px solid silver;
377 background: #f4f4f4;
378 padding: 0.5em;
381 div.quoteblock-attribution {
382 padding-top: 0.5em;
383 text-align: right;
386 div.verseblock-content {
387 white-space: pre;
389 div.verseblock-attribution {
390 padding-top: 0.75em;
391 text-align: left;
394 div.exampleblock-content {
395 border-left: 2px solid silver;
396 padding-left: 0.5em;
399 /* IE6 sets dynamically generated links as visited. */
400 div#toc a:visited { color: blue; }
401 </style>
402 </head>
403 <body>
404 <div id="header">
405 <h1>
406 git-filter-branch(1) Manual Page
407 </h1>
408 <h2>NAME</h2>
409 <div class="sectionbody">
410 <p>git-filter-branch -
411 Rewrite branches
412 </p>
413 </div>
414 </div>
415 <h2 id="_synopsis">SYNOPSIS</h2>
416 <div class="sectionbody">
417 <div class="verseblock">
418 <div class="verseblock-content"><em>git filter-branch</em> [--env-filter &lt;command&gt;] [--tree-filter &lt;command&gt;]
419 [--index-filter &lt;command&gt;] [--parent-filter &lt;command&gt;]
420 [--msg-filter &lt;command&gt;] [--commit-filter &lt;command&gt;]
421 [--tag-name-filter &lt;command&gt;] [--subdirectory-filter &lt;directory&gt;]
422 [--prune-empty]
423 [--original &lt;namespace&gt;] [-d &lt;directory&gt;] [-f | --force]
424 [--] [&lt;rev-list options&gt;&#8230;]</div>
425 <div class="verseblock-attribution">
426 </div></div>
427 </div>
428 <h2 id="_description">DESCRIPTION</h2>
429 <div class="sectionbody">
430 <div class="paragraph"><p>Lets you rewrite git revision history by rewriting the branches mentioned
431 in the &lt;rev-list options&gt;, applying custom filters on each revision.
432 Those filters can modify each tree (e.g. removing a file or running
433 a perl rewrite on all files) or information about each commit.
434 Otherwise, all information (including original commit times or merge
435 information) will be preserved.</p></div>
436 <div class="paragraph"><p>The command will only rewrite the <em>positive</em> refs mentioned in the
437 command line (e.g. if you pass <em>a..b</em>, only <em>b</em> will be rewritten).
438 If you specify no filters, the commits will be recommitted without any
439 changes, which would normally have no effect. Nevertheless, this may be
440 useful in the future for compensating for some git bugs or such,
441 therefore such a usage is permitted.</p></div>
442 <div class="paragraph"><p><strong>NOTE</strong>: This command honors <tt>.git/info/grafts</tt>. If you have any grafts
443 defined, running this command will make them permanent.</p></div>
444 <div class="paragraph"><p><strong>WARNING</strong>! The rewritten history will have different object names for all
445 the objects and will not converge with the original branch. You will not
446 be able to easily push and distribute the rewritten branch on top of the
447 original branch. Please do not use this command if you do not know the
448 full implications, and avoid using it anyway, if a simple single commit
449 would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM
450 REBASE" section in <a href="git-rebase.html">git-rebase(1)</a> for further information about
451 rewriting published history.)</p></div>
452 <div class="paragraph"><p>Always verify that the rewritten version is correct: The original refs,
453 if different from the rewritten ones, will be stored in the namespace
454 <em>refs/original/</em>.</p></div>
455 <div class="paragraph"><p>Note that since this operation is very I/O expensive, it might
456 be a good idea to redirect the temporary directory off-disk with the
457 <em>-d</em> option, e.g. on tmpfs. Reportedly the speedup is very noticeable.</p></div>
458 <h3 id="_filters">Filters</h3><div style="clear:left"></div>
459 <div class="paragraph"><p>The filters are applied in the order as listed below. The &lt;command&gt;
460 argument is always evaluated in the shell context using the <em>eval</em> command
461 (with the notable exception of the commit filter, for technical reasons).
462 Prior to that, the $GIT_COMMIT environment variable will be set to contain
463 the id of the commit being rewritten. Also, GIT_AUTHOR_NAME,
464 GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,
465 and GIT_COMMITTER_DATE are set according to the current commit. The values
466 of these variables after the filters have run, are used for the new commit.
467 If any evaluation of &lt;command&gt; returns a non-zero exit status, the whole
468 operation will be aborted.</p></div>
469 <div class="paragraph"><p>A <em>map</em> function is available that takes an "original sha1 id" argument
470 and outputs a "rewritten sha1 id" if the commit has been already
471 rewritten, and "original sha1 id" otherwise; the <em>map</em> function can
472 return several ids on separate lines if your commit filter emitted
473 multiple commits.</p></div>
474 </div>
475 <h2 id="_options">OPTIONS</h2>
476 <div class="sectionbody">
477 <div class="dlist"><dl>
478 <dt class="hdlist1">
479 --env-filter &lt;command&gt;
480 </dt>
481 <dd>
483 This filter may be used if you only need to modify the environment
484 in which the commit will be performed. Specifically, you might
485 want to rewrite the author/committer name/email/time environment
486 variables (see <a href="git-commit-tree.html">git-commit-tree(1)</a> for details). Do not forget
487 to re-export the variables.
488 </p>
489 </dd>
490 <dt class="hdlist1">
491 --tree-filter &lt;command&gt;
492 </dt>
493 <dd>
495 This is the filter for rewriting the tree and its contents.
496 The argument is evaluated in shell with the working
497 directory set to the root of the checked out tree. The new tree
498 is then used as-is (new files are auto-added, disappeared files
499 are auto-removed - neither .gitignore files nor any other ignore
500 rules <strong>HAVE ANY EFFECT</strong>!).
501 </p>
502 </dd>
503 <dt class="hdlist1">
504 --index-filter &lt;command&gt;
505 </dt>
506 <dd>
508 This is the filter for rewriting the index. It is similar to the
509 tree filter but does not check out the tree, which makes it much
510 faster. Frequently used with <tt>git rm --cached
511 --ignore-unmatch &#8230;</tt>, see EXAMPLES below. For hairy
512 cases, see <a href="git-update-index.html">git-update-index(1)</a>.
513 </p>
514 </dd>
515 <dt class="hdlist1">
516 --parent-filter &lt;command&gt;
517 </dt>
518 <dd>
520 This is the filter for rewriting the commit&#8217;s parent list.
521 It will receive the parent string on stdin and shall output
522 the new parent string on stdout. The parent string is in
523 the format described in <a href="git-commit-tree.html">git-commit-tree(1)</a>: empty for
524 the initial commit, "-p parent" for a normal commit and
525 "-p parent1 -p parent2 -p parent3 &#8230;" for a merge commit.
526 </p>
527 </dd>
528 <dt class="hdlist1">
529 --msg-filter &lt;command&gt;
530 </dt>
531 <dd>
533 This is the filter for rewriting the commit messages.
534 The argument is evaluated in the shell with the original
535 commit message on standard input; its standard output is
536 used as the new commit message.
537 </p>
538 </dd>
539 <dt class="hdlist1">
540 --commit-filter &lt;command&gt;
541 </dt>
542 <dd>
544 This is the filter for performing the commit.
545 If this filter is specified, it will be called instead of the
546 <em>git commit-tree</em> command, with arguments of the form
547 "&lt;TREE_ID&gt; [(-p &lt;PARENT_COMMIT_ID&gt;)&#8230;]" and the log message on
548 stdin. The commit id is expected on stdout.
549 </p>
550 <div class="paragraph"><p>As a special extension, the commit filter may emit multiple
551 commit ids; in that case, the rewritten children of the original commit will
552 have all of them as parents.</p></div>
553 <div class="paragraph"><p>You can use the <em>map</em> convenience function in this filter, and other
554 convenience functions, too. For example, calling <em>skip_commit "$@"</em>
555 will leave out the current commit (but not its changes! If you want
556 that, use <em>git rebase</em> instead).</p></div>
557 <div class="paragraph"><p>You can also use the <tt>git_commit_non_empty_tree "$@"</tt> instead of
558 <tt>git commit-tree "$@"</tt> if you don&#8217;t wish to keep commits with a single parent
559 and that makes no change to the tree.</p></div>
560 </dd>
561 <dt class="hdlist1">
562 --tag-name-filter &lt;command&gt;
563 </dt>
564 <dd>
566 This is the filter for rewriting tag names. When passed,
567 it will be called for every tag ref that points to a rewritten
568 object (or to a tag object which points to a rewritten object).
569 The original tag name is passed via standard input, and the new
570 tag name is expected on standard output.
571 </p>
572 <div class="paragraph"><p>The original tags are not deleted, but can be overwritten;
573 use "--tag-name-filter cat" to simply update the tags. In this
574 case, be very careful and make sure you have the old tags
575 backed up in case the conversion has run afoul.</p></div>
576 <div class="paragraph"><p>Nearly proper rewriting of tag objects is supported. If the tag has
577 a message attached, a new tag object will be created with the same message,
578 author, and timestamp. If the tag has a signature attached, the
579 signature will be stripped. It is by definition impossible to preserve
580 signatures. The reason this is "nearly" proper, is because ideally if
581 the tag did not change (points to the same object, has the same name, etc.)
582 it should retain any signature. That is not the case, signatures will always
583 be removed, buyer beware. There is also no support for changing the
584 author or timestamp (or the tag message for that matter). Tags which point
585 to other tags will be rewritten to point to the underlying commit.</p></div>
586 </dd>
587 <dt class="hdlist1">
588 --subdirectory-filter &lt;directory&gt;
589 </dt>
590 <dd>
592 Only look at the history which touches the given subdirectory.
593 The result will contain that directory (and only that) as its
594 project root. Implies <a href="#Remap_to_ancestor">[Remap_to_ancestor]</a>.
595 </p>
596 </dd>
597 <dt class="hdlist1">
598 --prune-empty
599 </dt>
600 <dd>
602 Some kind of filters will generate empty commits, that left the tree
603 untouched. This switch allow git-filter-branch to ignore such
604 commits. Though, this switch only applies for commits that have one
605 and only one parent, it will hence keep merges points. Also, this
606 option is not compatible with the use of <em>--commit-filter</em>. Though you
607 just need to use the function <em>git_commit_non_empty_tree "$@"</em> instead
608 of the <tt>git commit-tree "$@"</tt> idiom in your commit filter to make that
609 happen.
610 </p>
611 </dd>
612 <dt class="hdlist1">
613 --original &lt;namespace&gt;
614 </dt>
615 <dd>
617 Use this option to set the namespace where the original commits
618 will be stored. The default value is <em>refs/original</em>.
619 </p>
620 </dd>
621 <dt class="hdlist1">
622 -d &lt;directory&gt;
623 </dt>
624 <dd>
626 Use this option to set the path to the temporary directory used for
627 rewriting. When applying a tree filter, the command needs to
628 temporarily check out the tree to some directory, which may consume
629 considerable space in case of large projects. By default it
630 does this in the <em>.git-rewrite/</em> directory but you can override
631 that choice by this parameter.
632 </p>
633 </dd>
634 <dt class="hdlist1">
636 </dt>
637 <dt class="hdlist1">
638 --force
639 </dt>
640 <dd>
642 <em>git filter-branch</em> refuses to start with an existing temporary
643 directory or when there are already refs starting with
644 <em>refs/original/</em>, unless forced.
645 </p>
646 </dd>
647 <dt class="hdlist1">
648 &lt;rev-list options&gt;&#8230;
649 </dt>
650 <dd>
652 Arguments for <em>git rev-list</em>. All positive refs included by
653 these options are rewritten. You may also specify options
654 such as <em>--all</em>, but you must use <em>--</em> to separate them from
655 the <em>git filter-branch</em> options. Implies <a href="#Remap_to_ancestor">[Remap_to_ancestor]</a>.
656 </p>
657 </dd>
658 </dl></div>
659 <h3 id="Remap_to_ancestor">Remap to ancestor</h3><div style="clear:left"></div>
660 <div class="paragraph"><p>By using <a href="rev-list.html">rev-list(1)</a> arguments, e.g., path limiters, you can limit the
661 set of revisions which get rewritten. However, positive refs on the command
662 line are distinguished: we don&#8217;t let them be excluded by such limiters. For
663 this purpose, they are instead rewritten to point at the nearest ancestor that
664 was not excluded.</p></div>
665 </div>
666 <h2 id="_examples">Examples</h2>
667 <div class="sectionbody">
668 <div class="paragraph"><p>Suppose you want to remove a file (containing confidential information
669 or copyright violation) from all commits:</p></div>
670 <div class="listingblock">
671 <div class="content">
672 <pre><tt>git filter-branch --tree-filter 'rm filename' HEAD</tt></pre>
673 </div></div>
674 <div class="paragraph"><p>However, if the file is absent from the tree of some commit,
675 a simple <tt>rm filename</tt> will fail for that tree and commit.
676 Thus you may instead want to use <tt>rm -f filename</tt> as the script.</p></div>
677 <div class="paragraph"><p>Using <tt>--index-filter</tt> with <em>git rm</em> yields a significantly faster
678 version. Like with using <tt>rm filename</tt>, <tt>git rm --cached filename</tt>
679 will fail if the file is absent from the tree of a commit. If you
680 want to "completely forget" a file, it does not matter when it entered
681 history, so we also add <tt>--ignore-unmatch</tt>:</p></div>
682 <div class="listingblock">
683 <div class="content">
684 <pre><tt>git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD</tt></pre>
685 </div></div>
686 <div class="paragraph"><p>Now, you will get the rewritten history saved in HEAD.</p></div>
687 <div class="paragraph"><p>To rewrite the repository to look as if <tt>foodir/</tt> had been its project
688 root, and discard all other history:</p></div>
689 <div class="listingblock">
690 <div class="content">
691 <pre><tt>git filter-branch --subdirectory-filter foodir -- --all</tt></pre>
692 </div></div>
693 <div class="paragraph"><p>Thus you can, e.g., turn a library subdirectory into a repository of
694 its own. Note the <tt>--</tt> that separates <em>filter-branch</em> options from
695 revision options, and the <tt>--all</tt> to rewrite all branches and tags.</p></div>
696 <div class="paragraph"><p>To set a commit (which typically is at the tip of another
697 history) to be the parent of the current initial commit, in
698 order to paste the other history behind the current history:</p></div>
699 <div class="listingblock">
700 <div class="content">
701 <pre><tt>git filter-branch --parent-filter 'sed "s/^\$/-p &lt;graft-id&gt;/"' HEAD</tt></pre>
702 </div></div>
703 <div class="paragraph"><p>(if the parent string is empty - which happens when we are dealing with
704 the initial commit - add graftcommit as a parent). Note that this assumes
705 history with a single root (that is, no merge without common ancestors
706 happened). If this is not the case, use:</p></div>
707 <div class="listingblock">
708 <div class="content">
709 <pre><tt>git filter-branch --parent-filter \
710 'test $GIT_COMMIT = &lt;commit-id&gt; &amp;&amp; echo "-p &lt;graft-id&gt;" || cat' HEAD</tt></pre>
711 </div></div>
712 <div class="paragraph"><p>or even simpler:</p></div>
713 <div class="listingblock">
714 <div class="content">
715 <pre><tt>echo "$commit-id $graft-id" &gt;&gt; .git/info/grafts
716 git filter-branch $graft-id..HEAD</tt></pre>
717 </div></div>
718 <div class="paragraph"><p>To remove commits authored by "Darl McBribe" from the history:</p></div>
719 <div class="listingblock">
720 <div class="content">
721 <pre><tt>git filter-branch --commit-filter '
722 if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
723 then
724 skip_commit "$@";
725 else
726 git commit-tree "$@";
727 fi' HEAD</tt></pre>
728 </div></div>
729 <div class="paragraph"><p>The function <em>skip_commit</em> is defined as follows:</p></div>
730 <div class="listingblock">
731 <div class="content">
732 <pre><tt>skip_commit()
734 shift;
735 while [ -n "$1" ];
737 shift;
738 map "$1";
739 shift;
740 done;
741 }</tt></pre>
742 </div></div>
743 <div class="paragraph"><p>The shift magic first throws away the tree id and then the -p
744 parameters. Note that this handles merges properly! In case Darl
745 committed a merge between P1 and P2, it will be propagated properly
746 and all children of the merge will become merge commits with P1,P2
747 as their parents instead of the merge commit.</p></div>
748 <div class="paragraph"><p>You can rewrite the commit log messages using <tt>--msg-filter</tt>. For
749 example, <em>git svn-id</em> strings in a repository created by <em>git svn</em> can
750 be removed this way:</p></div>
751 <div class="listingblock">
752 <div class="content">
753 <pre><tt>git filter-branch --msg-filter '
754 sed -e "/^git-svn-id:/d"
755 '</tt></pre>
756 </div></div>
757 <div class="paragraph"><p>To restrict rewriting to only part of the history, specify a revision
758 range in addition to the new branch name. The new branch name will
759 point to the top-most revision that a <em>git rev-list</em> of this range
760 will print.</p></div>
761 <div class="paragraph"><p>If you need to add <em>Acked-by</em> lines to, say, the last 10 commits (none
762 of which is a merge), use this command:</p></div>
763 <div class="listingblock">
764 <div class="content">
765 <pre><tt>git filter-branch --msg-filter '
766 cat &amp;&amp;
767 echo "Acked-by: Bugs Bunny &lt;bunny@bugzilla.org&gt;"
768 ' HEAD~10..HEAD</tt></pre>
769 </div></div>
770 <div class="paragraph"><p><strong>NOTE</strong> the changes introduced by the commits, and which are not reverted
771 by subsequent commits, will still be in the rewritten branch. If you want
772 to throw out <em>changes</em> together with the commits, you should use the
773 interactive mode of <em>git rebase</em>.</p></div>
774 <div class="paragraph"><p>Consider this history:</p></div>
775 <div class="listingblock">
776 <div class="content">
777 <pre><tt> D--E--F--G--H
779 A--B-----C</tt></pre>
780 </div></div>
781 <div class="paragraph"><p>To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:</p></div>
782 <div class="listingblock">
783 <div class="content">
784 <pre><tt>git filter-branch ... C..H</tt></pre>
785 </div></div>
786 <div class="paragraph"><p>To rewrite commits E,F,G,H, use one of these:</p></div>
787 <div class="listingblock">
788 <div class="content">
789 <pre><tt>git filter-branch ... C..H --not D
790 git filter-branch ... D..H --not C</tt></pre>
791 </div></div>
792 <div class="paragraph"><p>To move the whole tree into a subdirectory, or remove it from there:</p></div>
793 <div class="listingblock">
794 <div class="content">
795 <pre><tt>git filter-branch --index-filter \
796 'git ls-files -s | sed "s-\t\"*-&amp;newsubdir/-" |
797 GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
798 git update-index --index-info &amp;&amp;
799 mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD</tt></pre>
800 </div></div>
801 </div>
802 <h2 id="_checklist_for_shrinking_a_repository">Checklist for Shrinking a Repository</h2>
803 <div class="sectionbody">
804 <div class="paragraph"><p>git-filter-branch is often used to get rid of a subset of files,
805 usually with some combination of <tt>--index-filter</tt> and
806 <tt>--subdirectory-filter</tt>. People expect the resulting repository to
807 be smaller than the original, but you need a few more steps to
808 actually make it smaller, because git tries hard not to lose your
809 objects until you tell it to. First make sure that:</p></div>
810 <div class="ulist"><ul>
811 <li>
813 You really removed all variants of a filename, if a blob was moved
814 over its lifetime. <tt>git log --name-only --follow --all --
815 filename</tt> can help you find renames.
816 </p>
817 </li>
818 <li>
820 You really filtered all refs: use <tt>--tag-name-filter cat --
821 --all</tt> when calling git-filter-branch.
822 </p>
823 </li>
824 </ul></div>
825 <div class="paragraph"><p>Then there are two ways to get a smaller repository. A safer way is
826 to clone, that keeps your original intact.</p></div>
827 <div class="ulist"><ul>
828 <li>
830 Clone it with <tt>git clone file:///path/to/repo</tt>. The clone
831 will not have the removed objects. See <a href="git-clone.html">git-clone(1)</a>. (Note
832 that cloning with a plain path just hardlinks everything!)
833 </p>
834 </li>
835 </ul></div>
836 <div class="paragraph"><p>If you really don&#8217;t want to clone it, for whatever reasons, check the
837 following points instead (in this order). This is a very destructive
838 approach, so <strong>make a backup</strong> or go back to cloning it. You have been
839 warned.</p></div>
840 <div class="ulist"><ul>
841 <li>
843 Remove the original refs backed up by git-filter-branch: say <tt>git
844 for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git
845 update-ref -d</tt>.
846 </p>
847 </li>
848 <li>
850 Expire all reflogs with <tt>git reflog expire --expire=now --all</tt>.
851 </p>
852 </li>
853 <li>
855 Garbage collect all unreferenced objects with <tt>git gc --prune=now</tt>
856 (or if your git-gc is not new enough to support arguments to
857 <tt>--prune</tt>, use <tt>git repack -ad; git prune</tt> instead).
858 </p>
859 </li>
860 </ul></div>
861 </div>
862 <h2 id="_author">Author</h2>
863 <div class="sectionbody">
864 <div class="paragraph"><p>Written by Petr "Pasky" Baudis &lt;<a href="mailto:pasky@suse.cz">pasky@suse.cz</a>&gt;,
865 and the git list &lt;<a href="mailto:git@vger.kernel.org">git@vger.kernel.org</a>&gt;</p></div>
866 </div>
867 <h2 id="_documentation">Documentation</h2>
868 <div class="sectionbody">
869 <div class="paragraph"><p>Documentation by Petr Baudis and the git list.</p></div>
870 </div>
871 <h2 id="_git">GIT</h2>
872 <div class="sectionbody">
873 <div class="paragraph"><p>Part of the <a href="git.html">git(1)</a> suite</p></div>
874 </div>
875 <div id="footer">
876 <div id="footer-text">
877 Last updated 2010-11-06 00:41:57 UTC
878 </div>
879 </div>
880 </body>
881 </html>