Autogenerated HTML docs for v1.7.7-290-gc9e7aa
[git/jnareb-git.git] / git-filter-branch.html
blob8ae859e027d0e249e5229cbbdc8fdfd37acd1ae9
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.5.2" />
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.0em;
122 margin-bottom: 1.5em;
124 div.admonitionblock {
125 margin-top: 2.0em;
126 margin-bottom: 2.0em;
127 margin-right: 10%;
128 color: #606060;
131 div.content { /* Block element content. */
132 padding: 0;
135 /* Block element titles. */
136 div.title, caption.title {
137 color: #527bbd;
138 font-family: sans-serif;
139 font-weight: bold;
140 text-align: left;
141 margin-top: 1.0em;
142 margin-bottom: 0.5em;
144 div.title + * {
145 margin-top: 0;
148 td div.title:first-child {
149 margin-top: 0.0em;
151 div.content div.title:first-child {
152 margin-top: 0.0em;
154 div.content + div.title {
155 margin-top: 0.0em;
158 div.sidebarblock > div.content {
159 background: #ffffee;
160 border: 1px solid silver;
161 padding: 0.5em;
164 div.listingblock > div.content {
165 border: 1px solid silver;
166 background: #f4f4f4;
167 padding: 0.5em;
170 div.quoteblock, div.verseblock {
171 padding-left: 1.0em;
172 margin-left: 1.0em;
173 margin-right: 10%;
174 border-left: 5px solid #dddddd;
175 color: #777777;
178 div.quoteblock > div.attribution {
179 padding-top: 0.5em;
180 text-align: right;
183 div.verseblock > div.content {
184 white-space: pre;
186 div.verseblock > div.attribution {
187 padding-top: 0.75em;
188 text-align: left;
190 /* DEPRECATED: Pre version 8.2.7 verse style literal block. */
191 div.verseblock + div.attribution {
192 text-align: left;
195 div.admonitionblock .icon {
196 vertical-align: top;
197 font-size: 1.1em;
198 font-weight: bold;
199 text-decoration: underline;
200 color: #527bbd;
201 padding-right: 0.5em;
203 div.admonitionblock td.content {
204 padding-left: 0.5em;
205 border-left: 3px solid #dddddd;
208 div.exampleblock > div.content {
209 border-left: 3px solid #dddddd;
210 padding-left: 0.5em;
213 div.imageblock div.content { padding-left: 0; }
214 span.image img { border-style: none; }
215 a.image:visited { color: white; }
217 dl {
218 margin-top: 0.8em;
219 margin-bottom: 0.8em;
221 dt {
222 margin-top: 0.5em;
223 margin-bottom: 0;
224 font-style: normal;
225 color: navy;
227 dd > *:first-child {
228 margin-top: 0.1em;
231 ul, ol {
232 list-style-position: outside;
234 ol.arabic {
235 list-style-type: decimal;
237 ol.loweralpha {
238 list-style-type: lower-alpha;
240 ol.upperalpha {
241 list-style-type: upper-alpha;
243 ol.lowerroman {
244 list-style-type: lower-roman;
246 ol.upperroman {
247 list-style-type: upper-roman;
250 div.compact ul, div.compact ol,
251 div.compact p, div.compact p,
252 div.compact div, div.compact div {
253 margin-top: 0.1em;
254 margin-bottom: 0.1em;
257 div.tableblock > table {
258 border: 3px solid #527bbd;
260 thead, p.table.header {
261 font-family: sans-serif;
262 font-weight: bold;
264 tfoot {
265 font-weight: bold;
267 td > div.verse {
268 white-space: pre;
270 p.table {
271 margin-top: 0;
273 /* Because the table frame attribute is overriden by CSS in most browsers. */
274 div.tableblock > table[frame="void"] {
275 border-style: none;
277 div.tableblock > table[frame="hsides"] {
278 border-left-style: none;
279 border-right-style: none;
281 div.tableblock > table[frame="vsides"] {
282 border-top-style: none;
283 border-bottom-style: none;
287 div.hdlist {
288 margin-top: 0.8em;
289 margin-bottom: 0.8em;
291 div.hdlist tr {
292 padding-bottom: 15px;
294 dt.hdlist1.strong, td.hdlist1.strong {
295 font-weight: bold;
297 td.hdlist1 {
298 vertical-align: top;
299 font-style: normal;
300 padding-right: 0.8em;
301 color: navy;
303 td.hdlist2 {
304 vertical-align: top;
306 div.hdlist.compact tr {
307 margin: 0;
308 padding-bottom: 0;
311 .comment {
312 background: yellow;
315 .footnote, .footnoteref {
316 font-size: 0.8em;
319 span.footnote, span.footnoteref {
320 vertical-align: super;
323 #footnotes {
324 margin: 20px 0 20px 0;
325 padding: 7px 0 0 0;
328 #footnotes div.footnote {
329 margin: 0 0 5px 0;
332 #footnotes hr {
333 border: none;
334 border-top: 1px solid silver;
335 height: 1px;
336 text-align: left;
337 margin-left: 0;
338 width: 20%;
339 min-width: 100px;
343 @media print {
344 div#footer-badges { display: none; }
347 div#toc {
348 margin-bottom: 2.5em;
351 div#toctitle {
352 color: #527bbd;
353 font-family: sans-serif;
354 font-size: 1.1em;
355 font-weight: bold;
356 margin-top: 1.0em;
357 margin-bottom: 0.1em;
360 div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
361 margin-top: 0;
362 margin-bottom: 0;
364 div.toclevel2 {
365 margin-left: 2em;
366 font-size: 0.9em;
368 div.toclevel3 {
369 margin-left: 4em;
370 font-size: 0.9em;
372 div.toclevel4 {
373 margin-left: 6em;
374 font-size: 0.9em;
376 /* Overrides for manpage documents */
377 h1 {
378 padding-top: 0.5em;
379 padding-bottom: 0.5em;
380 border-top: 2px solid silver;
381 border-bottom: 2px solid silver;
383 h2 {
384 border-style: none;
386 div.sectionbody {
387 margin-left: 5%;
390 @media print {
391 div#toc { display: none; }
394 /* Workarounds for IE6's broken and incomplete CSS2. */
396 div.sidebar-content {
397 background: #ffffee;
398 border: 1px solid silver;
399 padding: 0.5em;
401 div.sidebar-title, div.image-title {
402 color: #527bbd;
403 font-family: sans-serif;
404 font-weight: bold;
405 margin-top: 0.0em;
406 margin-bottom: 0.5em;
409 div.listingblock div.content {
410 border: 1px solid silver;
411 background: #f4f4f4;
412 padding: 0.5em;
415 div.quoteblock-attribution {
416 padding-top: 0.5em;
417 text-align: right;
420 div.verseblock-content {
421 white-space: pre;
423 div.verseblock-attribution {
424 padding-top: 0.75em;
425 text-align: left;
428 div.exampleblock-content {
429 border-left: 3px solid #dddddd;
430 padding-left: 0.5em;
433 /* IE6 sets dynamically generated links as visited. */
434 div#toc a:visited { color: blue; }
435 </style>
436 <script type="text/javascript">
437 /*<![CDATA[*/
438 window.onload = function(){asciidoc.footnotes();}
439 var asciidoc = { // Namespace.
441 /////////////////////////////////////////////////////////////////////
442 // Table Of Contents generator
443 /////////////////////////////////////////////////////////////////////
445 /* Author: Mihai Bazon, September 2002
446 * http://students.infoiasi.ro/~mishoo
448 * Table Of Content generator
449 * Version: 0.4
451 * Feel free to use this script under the terms of the GNU General Public
452 * License, as long as you do not remove or alter this notice.
455 /* modified by Troy D. Hanson, September 2006. License: GPL */
456 /* modified by Stuart Rackham, 2006, 2009. License: GPL */
458 // toclevels = 1..4.
459 toc: function (toclevels) {
461 function getText(el) {
462 var text = "";
463 for (var i = el.firstChild; i != null; i = i.nextSibling) {
464 if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
465 text += i.data;
466 else if (i.firstChild != null)
467 text += getText(i);
469 return text;
472 function TocEntry(el, text, toclevel) {
473 this.element = el;
474 this.text = text;
475 this.toclevel = toclevel;
478 function tocEntries(el, toclevels) {
479 var result = new Array;
480 var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
481 // Function that scans the DOM tree for header elements (the DOM2
482 // nodeIterator API would be a better technique but not supported by all
483 // browsers).
484 var iterate = function (el) {
485 for (var i = el.firstChild; i != null; i = i.nextSibling) {
486 if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
487 var mo = re.exec(i.tagName);
488 if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
489 result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
491 iterate(i);
495 iterate(el);
496 return result;
499 var toc = document.getElementById("toc");
500 var entries = tocEntries(document.getElementById("content"), toclevels);
501 for (var i = 0; i < entries.length; ++i) {
502 var entry = entries[i];
503 if (entry.element.id == "")
504 entry.element.id = "_toc_" + i;
505 var a = document.createElement("a");
506 a.href = "#" + entry.element.id;
507 a.appendChild(document.createTextNode(entry.text));
508 var div = document.createElement("div");
509 div.appendChild(a);
510 div.className = "toclevel" + entry.toclevel;
511 toc.appendChild(div);
513 if (entries.length == 0)
514 toc.parentNode.removeChild(toc);
518 /////////////////////////////////////////////////////////////////////
519 // Footnotes generator
520 /////////////////////////////////////////////////////////////////////
522 /* Based on footnote generation code from:
523 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
526 footnotes: function () {
527 var cont = document.getElementById("content");
528 var noteholder = document.getElementById("footnotes");
529 var spans = cont.getElementsByTagName("span");
530 var refs = {};
531 var n = 0;
532 for (i=0; i<spans.length; i++) {
533 if (spans[i].className == "footnote") {
534 n++;
535 // Use [\s\S] in place of . so multi-line matches work.
536 // Because JavaScript has no s (dotall) regex flag.
537 note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
538 noteholder.innerHTML +=
539 "<div class='footnote' id='_footnote_" + n + "'>" +
540 "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
541 n + "</a>. " + note + "</div>";
542 spans[i].innerHTML =
543 "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
544 "' title='View footnote' class='footnote'>" + n + "</a>]";
545 var id =spans[i].getAttribute("id");
546 if (id != null) refs["#"+id] = n;
549 if (n == 0)
550 noteholder.parentNode.removeChild(noteholder);
551 else {
552 // Process footnoterefs.
553 for (i=0; i<spans.length; i++) {
554 if (spans[i].className == "footnoteref") {
555 var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
556 href = href.match(/#.*/)[0]; // Because IE return full URL.
557 n = refs[href];
558 spans[i].innerHTML =
559 "[<a href='#_footnote_" + n +
560 "' title='View footnote' class='footnote'>" + n + "</a>]";
567 /*]]>*/
568 </script>
569 </head>
570 <body>
571 <div id="header">
572 <h1>
573 git-filter-branch(1) Manual Page
574 </h1>
575 <h2>NAME</h2>
576 <div class="sectionbody">
577 <p>git-filter-branch -
578 Rewrite branches
579 </p>
580 </div>
581 </div>
582 <div id="content">
583 <h2 id="_synopsis">SYNOPSIS</h2>
584 <div class="sectionbody">
585 <div class="verseblock">
586 <div class="verseblock-content"><em>git filter-branch</em> [--env-filter &lt;command&gt;] [--tree-filter &lt;command&gt;]
587 [--index-filter &lt;command&gt;] [--parent-filter &lt;command&gt;]
588 [--msg-filter &lt;command&gt;] [--commit-filter &lt;command&gt;]
589 [--tag-name-filter &lt;command&gt;] [--subdirectory-filter &lt;directory&gt;]
590 [--prune-empty]
591 [--original &lt;namespace&gt;] [-d &lt;directory&gt;] [-f | --force]
592 [--] [&lt;rev-list options&gt;&#8230;]</div>
593 <div class="verseblock-attribution">
594 </div></div>
595 </div>
596 <h2 id="_description">DESCRIPTION</h2>
597 <div class="sectionbody">
598 <div class="paragraph"><p>Lets you rewrite git revision history by rewriting the branches mentioned
599 in the &lt;rev-list options&gt;, applying custom filters on each revision.
600 Those filters can modify each tree (e.g. removing a file or running
601 a perl rewrite on all files) or information about each commit.
602 Otherwise, all information (including original commit times or merge
603 information) will be preserved.</p></div>
604 <div class="paragraph"><p>The command will only rewrite the <em>positive</em> refs mentioned in the
605 command line (e.g. if you pass <em>a..b</em>, only <em>b</em> will be rewritten).
606 If you specify no filters, the commits will be recommitted without any
607 changes, which would normally have no effect. Nevertheless, this may be
608 useful in the future for compensating for some git bugs or such,
609 therefore such a usage is permitted.</p></div>
610 <div class="paragraph"><p><strong>NOTE</strong>: This command honors <tt>.git/info/grafts</tt> and <tt>.git/refs/replace/</tt>.
611 If you have any grafts or replacement refs defined, running this command
612 will make them permanent.</p></div>
613 <div class="paragraph"><p><strong>WARNING</strong>! The rewritten history will have different object names for all
614 the objects and will not converge with the original branch. You will not
615 be able to easily push and distribute the rewritten branch on top of the
616 original branch. Please do not use this command if you do not know the
617 full implications, and avoid using it anyway, if a simple single commit
618 would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM
619 REBASE" section in <a href="git-rebase.html">git-rebase(1)</a> for further information about
620 rewriting published history.)</p></div>
621 <div class="paragraph"><p>Always verify that the rewritten version is correct: The original refs,
622 if different from the rewritten ones, will be stored in the namespace
623 <em>refs/original/</em>.</p></div>
624 <div class="paragraph"><p>Note that since this operation is very I/O expensive, it might
625 be a good idea to redirect the temporary directory off-disk with the
626 <em>-d</em> option, e.g. on tmpfs. Reportedly the speedup is very noticeable.</p></div>
627 <h3 id="_filters">Filters</h3><div style="clear:left"></div>
628 <div class="paragraph"><p>The filters are applied in the order as listed below. The &lt;command&gt;
629 argument is always evaluated in the shell context using the <em>eval</em> command
630 (with the notable exception of the commit filter, for technical reasons).
631 Prior to that, the $GIT_COMMIT environment variable will be set to contain
632 the id of the commit being rewritten. Also, GIT_AUTHOR_NAME,
633 GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,
634 and GIT_COMMITTER_DATE are set according to the current commit. The values
635 of these variables after the filters have run, are used for the new commit.
636 If any evaluation of &lt;command&gt; returns a non-zero exit status, the whole
637 operation will be aborted.</p></div>
638 <div class="paragraph"><p>A <em>map</em> function is available that takes an "original sha1 id" argument
639 and outputs a "rewritten sha1 id" if the commit has been already
640 rewritten, and "original sha1 id" otherwise; the <em>map</em> function can
641 return several ids on separate lines if your commit filter emitted
642 multiple commits.</p></div>
643 </div>
644 <h2 id="_options">OPTIONS</h2>
645 <div class="sectionbody">
646 <div class="dlist"><dl>
647 <dt class="hdlist1">
648 --env-filter &lt;command&gt;
649 </dt>
650 <dd>
652 This filter may be used if you only need to modify the environment
653 in which the commit will be performed. Specifically, you might
654 want to rewrite the author/committer name/email/time environment
655 variables (see <a href="git-commit-tree.html">git-commit-tree(1)</a> for details). Do not forget
656 to re-export the variables.
657 </p>
658 </dd>
659 <dt class="hdlist1">
660 --tree-filter &lt;command&gt;
661 </dt>
662 <dd>
664 This is the filter for rewriting the tree and its contents.
665 The argument is evaluated in shell with the working
666 directory set to the root of the checked out tree. The new tree
667 is then used as-is (new files are auto-added, disappeared files
668 are auto-removed - neither .gitignore files nor any other ignore
669 rules <strong>HAVE ANY EFFECT</strong>!).
670 </p>
671 </dd>
672 <dt class="hdlist1">
673 --index-filter &lt;command&gt;
674 </dt>
675 <dd>
677 This is the filter for rewriting the index. It is similar to the
678 tree filter but does not check out the tree, which makes it much
679 faster. Frequently used with <tt>git rm --cached
680 --ignore-unmatch &#8230;</tt>, see EXAMPLES below. For hairy
681 cases, see <a href="git-update-index.html">git-update-index(1)</a>.
682 </p>
683 </dd>
684 <dt class="hdlist1">
685 --parent-filter &lt;command&gt;
686 </dt>
687 <dd>
689 This is the filter for rewriting the commit&#8217;s parent list.
690 It will receive the parent string on stdin and shall output
691 the new parent string on stdout. The parent string is in
692 the format described in <a href="git-commit-tree.html">git-commit-tree(1)</a>: empty for
693 the initial commit, "-p parent" for a normal commit and
694 "-p parent1 -p parent2 -p parent3 &#8230;" for a merge commit.
695 </p>
696 </dd>
697 <dt class="hdlist1">
698 --msg-filter &lt;command&gt;
699 </dt>
700 <dd>
702 This is the filter for rewriting the commit messages.
703 The argument is evaluated in the shell with the original
704 commit message on standard input; its standard output is
705 used as the new commit message.
706 </p>
707 </dd>
708 <dt class="hdlist1">
709 --commit-filter &lt;command&gt;
710 </dt>
711 <dd>
713 This is the filter for performing the commit.
714 If this filter is specified, it will be called instead of the
715 <em>git commit-tree</em> command, with arguments of the form
716 "&lt;TREE_ID&gt; [(-p &lt;PARENT_COMMIT_ID&gt;)&#8230;]" and the log message on
717 stdin. The commit id is expected on stdout.
718 </p>
719 <div class="paragraph"><p>As a special extension, the commit filter may emit multiple
720 commit ids; in that case, the rewritten children of the original commit will
721 have all of them as parents.</p></div>
722 <div class="paragraph"><p>You can use the <em>map</em> convenience function in this filter, and other
723 convenience functions, too. For example, calling <em>skip_commit "$@"</em>
724 will leave out the current commit (but not its changes! If you want
725 that, use <em>git rebase</em> instead).</p></div>
726 <div class="paragraph"><p>You can also use the <tt>git_commit_non_empty_tree "$@"</tt> instead of
727 <tt>git commit-tree "$@"</tt> if you don&#8217;t wish to keep commits with a single parent
728 and that makes no change to the tree.</p></div>
729 </dd>
730 <dt class="hdlist1">
731 --tag-name-filter &lt;command&gt;
732 </dt>
733 <dd>
735 This is the filter for rewriting tag names. When passed,
736 it will be called for every tag ref that points to a rewritten
737 object (or to a tag object which points to a rewritten object).
738 The original tag name is passed via standard input, and the new
739 tag name is expected on standard output.
740 </p>
741 <div class="paragraph"><p>The original tags are not deleted, but can be overwritten;
742 use "--tag-name-filter cat" to simply update the tags. In this
743 case, be very careful and make sure you have the old tags
744 backed up in case the conversion has run afoul.</p></div>
745 <div class="paragraph"><p>Nearly proper rewriting of tag objects is supported. If the tag has
746 a message attached, a new tag object will be created with the same message,
747 author, and timestamp. If the tag has a signature attached, the
748 signature will be stripped. It is by definition impossible to preserve
749 signatures. The reason this is "nearly" proper, is because ideally if
750 the tag did not change (points to the same object, has the same name, etc.)
751 it should retain any signature. That is not the case, signatures will always
752 be removed, buyer beware. There is also no support for changing the
753 author or timestamp (or the tag message for that matter). Tags which point
754 to other tags will be rewritten to point to the underlying commit.</p></div>
755 </dd>
756 <dt class="hdlist1">
757 --subdirectory-filter &lt;directory&gt;
758 </dt>
759 <dd>
761 Only look at the history which touches the given subdirectory.
762 The result will contain that directory (and only that) as its
763 project root. Implies <a href="#Remap_to_ancestor">[Remap_to_ancestor]</a>.
764 </p>
765 </dd>
766 <dt class="hdlist1">
767 --prune-empty
768 </dt>
769 <dd>
771 Some kind of filters will generate empty commits, that left the tree
772 untouched. This switch allow git-filter-branch to ignore such
773 commits. Though, this switch only applies for commits that have one
774 and only one parent, it will hence keep merges points. Also, this
775 option is not compatible with the use of <em>--commit-filter</em>. Though you
776 just need to use the function <em>git_commit_non_empty_tree "$@"</em> instead
777 of the <tt>git commit-tree "$@"</tt> idiom in your commit filter to make that
778 happen.
779 </p>
780 </dd>
781 <dt class="hdlist1">
782 --original &lt;namespace&gt;
783 </dt>
784 <dd>
786 Use this option to set the namespace where the original commits
787 will be stored. The default value is <em>refs/original</em>.
788 </p>
789 </dd>
790 <dt class="hdlist1">
791 -d &lt;directory&gt;
792 </dt>
793 <dd>
795 Use this option to set the path to the temporary directory used for
796 rewriting. When applying a tree filter, the command needs to
797 temporarily check out the tree to some directory, which may consume
798 considerable space in case of large projects. By default it
799 does this in the <em>.git-rewrite/</em> directory but you can override
800 that choice by this parameter.
801 </p>
802 </dd>
803 <dt class="hdlist1">
805 </dt>
806 <dt class="hdlist1">
807 --force
808 </dt>
809 <dd>
811 <em>git filter-branch</em> refuses to start with an existing temporary
812 directory or when there are already refs starting with
813 <em>refs/original/</em>, unless forced.
814 </p>
815 </dd>
816 <dt class="hdlist1">
817 &lt;rev-list options&gt;&#8230;
818 </dt>
819 <dd>
821 Arguments for <em>git rev-list</em>. All positive refs included by
822 these options are rewritten. You may also specify options
823 such as <em>--all</em>, but you must use <em>--</em> to separate them from
824 the <em>git filter-branch</em> options. Implies <a href="#Remap_to_ancestor">[Remap_to_ancestor]</a>.
825 </p>
826 </dd>
827 </dl></div>
828 <h3 id="Remap_to_ancestor">Remap to ancestor</h3><div style="clear:left"></div>
829 <div class="paragraph"><p>By using <a href="rev-list.html">rev-list(1)</a> arguments, e.g., path limiters, you can limit the
830 set of revisions which get rewritten. However, positive refs on the command
831 line are distinguished: we don&#8217;t let them be excluded by such limiters. For
832 this purpose, they are instead rewritten to point at the nearest ancestor that
833 was not excluded.</p></div>
834 </div>
835 <h2 id="_examples">Examples</h2>
836 <div class="sectionbody">
837 <div class="paragraph"><p>Suppose you want to remove a file (containing confidential information
838 or copyright violation) from all commits:</p></div>
839 <div class="listingblock">
840 <div class="content">
841 <pre><tt>git filter-branch --tree-filter 'rm filename' HEAD</tt></pre>
842 </div></div>
843 <div class="paragraph"><p>However, if the file is absent from the tree of some commit,
844 a simple <tt>rm filename</tt> will fail for that tree and commit.
845 Thus you may instead want to use <tt>rm -f filename</tt> as the script.</p></div>
846 <div class="paragraph"><p>Using <tt>--index-filter</tt> with <em>git rm</em> yields a significantly faster
847 version. Like with using <tt>rm filename</tt>, <tt>git rm --cached filename</tt>
848 will fail if the file is absent from the tree of a commit. If you
849 want to "completely forget" a file, it does not matter when it entered
850 history, so we also add <tt>--ignore-unmatch</tt>:</p></div>
851 <div class="listingblock">
852 <div class="content">
853 <pre><tt>git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD</tt></pre>
854 </div></div>
855 <div class="paragraph"><p>Now, you will get the rewritten history saved in HEAD.</p></div>
856 <div class="paragraph"><p>To rewrite the repository to look as if <tt>foodir/</tt> had been its project
857 root, and discard all other history:</p></div>
858 <div class="listingblock">
859 <div class="content">
860 <pre><tt>git filter-branch --subdirectory-filter foodir -- --all</tt></pre>
861 </div></div>
862 <div class="paragraph"><p>Thus you can, e.g., turn a library subdirectory into a repository of
863 its own. Note the <tt>--</tt> that separates <em>filter-branch</em> options from
864 revision options, and the <tt>--all</tt> to rewrite all branches and tags.</p></div>
865 <div class="paragraph"><p>To set a commit (which typically is at the tip of another
866 history) to be the parent of the current initial commit, in
867 order to paste the other history behind the current history:</p></div>
868 <div class="listingblock">
869 <div class="content">
870 <pre><tt>git filter-branch --parent-filter 'sed "s/^\$/-p &lt;graft-id&gt;/"' HEAD</tt></pre>
871 </div></div>
872 <div class="paragraph"><p>(if the parent string is empty - which happens when we are dealing with
873 the initial commit - add graftcommit as a parent). Note that this assumes
874 history with a single root (that is, no merge without common ancestors
875 happened). If this is not the case, use:</p></div>
876 <div class="listingblock">
877 <div class="content">
878 <pre><tt>git filter-branch --parent-filter \
879 'test $GIT_COMMIT = &lt;commit-id&gt; &amp;&amp; echo "-p &lt;graft-id&gt;" || cat' HEAD</tt></pre>
880 </div></div>
881 <div class="paragraph"><p>or even simpler:</p></div>
882 <div class="listingblock">
883 <div class="content">
884 <pre><tt>echo "$commit-id $graft-id" &gt;&gt; .git/info/grafts
885 git filter-branch $graft-id..HEAD</tt></pre>
886 </div></div>
887 <div class="paragraph"><p>To remove commits authored by "Darl McBribe" from the history:</p></div>
888 <div class="listingblock">
889 <div class="content">
890 <pre><tt>git filter-branch --commit-filter '
891 if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
892 then
893 skip_commit "$@";
894 else
895 git commit-tree "$@";
896 fi' HEAD</tt></pre>
897 </div></div>
898 <div class="paragraph"><p>The function <em>skip_commit</em> is defined as follows:</p></div>
899 <div class="listingblock">
900 <div class="content">
901 <pre><tt>skip_commit()
903 shift;
904 while [ -n "$1" ];
906 shift;
907 map "$1";
908 shift;
909 done;
910 }</tt></pre>
911 </div></div>
912 <div class="paragraph"><p>The shift magic first throws away the tree id and then the -p
913 parameters. Note that this handles merges properly! In case Darl
914 committed a merge between P1 and P2, it will be propagated properly
915 and all children of the merge will become merge commits with P1,P2
916 as their parents instead of the merge commit.</p></div>
917 <div class="paragraph"><p>You can rewrite the commit log messages using <tt>--msg-filter</tt>. For
918 example, <em>git svn-id</em> strings in a repository created by <em>git svn</em> can
919 be removed this way:</p></div>
920 <div class="listingblock">
921 <div class="content">
922 <pre><tt>git filter-branch --msg-filter '
923 sed -e "/^git-svn-id:/d"
924 '</tt></pre>
925 </div></div>
926 <div class="paragraph"><p>To restrict rewriting to only part of the history, specify a revision
927 range in addition to the new branch name. The new branch name will
928 point to the top-most revision that a <em>git rev-list</em> of this range
929 will print.</p></div>
930 <div class="paragraph"><p>If you need to add <em>Acked-by</em> lines to, say, the last 10 commits (none
931 of which is a merge), use this command:</p></div>
932 <div class="listingblock">
933 <div class="content">
934 <pre><tt>git filter-branch --msg-filter '
935 cat &amp;&amp;
936 echo "Acked-by: Bugs Bunny &lt;bunny@bugzilla.org&gt;"
937 ' HEAD~10..HEAD</tt></pre>
938 </div></div>
939 <div class="paragraph"><p><strong>NOTE</strong> the changes introduced by the commits, and which are not reverted
940 by subsequent commits, will still be in the rewritten branch. If you want
941 to throw out <em>changes</em> together with the commits, you should use the
942 interactive mode of <em>git rebase</em>.</p></div>
943 <div class="paragraph"><p>Consider this history:</p></div>
944 <div class="listingblock">
945 <div class="content">
946 <pre><tt> D--E--F--G--H
948 A--B-----C</tt></pre>
949 </div></div>
950 <div class="paragraph"><p>To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:</p></div>
951 <div class="listingblock">
952 <div class="content">
953 <pre><tt>git filter-branch ... C..H</tt></pre>
954 </div></div>
955 <div class="paragraph"><p>To rewrite commits E,F,G,H, use one of these:</p></div>
956 <div class="listingblock">
957 <div class="content">
958 <pre><tt>git filter-branch ... C..H --not D
959 git filter-branch ... D..H --not C</tt></pre>
960 </div></div>
961 <div class="paragraph"><p>To move the whole tree into a subdirectory, or remove it from there:</p></div>
962 <div class="listingblock">
963 <div class="content">
964 <pre><tt>git filter-branch --index-filter \
965 'git ls-files -s | sed "s-\t\"*-&amp;newsubdir/-" |
966 GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
967 git update-index --index-info &amp;&amp;
968 mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD</tt></pre>
969 </div></div>
970 </div>
971 <h2 id="_checklist_for_shrinking_a_repository">Checklist for Shrinking a Repository</h2>
972 <div class="sectionbody">
973 <div class="paragraph"><p>git-filter-branch is often used to get rid of a subset of files,
974 usually with some combination of <tt>--index-filter</tt> and
975 <tt>--subdirectory-filter</tt>. People expect the resulting repository to
976 be smaller than the original, but you need a few more steps to
977 actually make it smaller, because git tries hard not to lose your
978 objects until you tell it to. First make sure that:</p></div>
979 <div class="ulist"><ul>
980 <li>
982 You really removed all variants of a filename, if a blob was moved
983 over its lifetime. <tt>git log --name-only --follow --all --
984 filename</tt> can help you find renames.
985 </p>
986 </li>
987 <li>
989 You really filtered all refs: use <tt>--tag-name-filter cat --
990 --all</tt> when calling git-filter-branch.
991 </p>
992 </li>
993 </ul></div>
994 <div class="paragraph"><p>Then there are two ways to get a smaller repository. A safer way is
995 to clone, that keeps your original intact.</p></div>
996 <div class="ulist"><ul>
997 <li>
999 Clone it with <tt>git clone file:///path/to/repo</tt>. The clone
1000 will not have the removed objects. See <a href="git-clone.html">git-clone(1)</a>. (Note
1001 that cloning with a plain path just hardlinks everything!)
1002 </p>
1003 </li>
1004 </ul></div>
1005 <div class="paragraph"><p>If you really don&#8217;t want to clone it, for whatever reasons, check the
1006 following points instead (in this order). This is a very destructive
1007 approach, so <strong>make a backup</strong> or go back to cloning it. You have been
1008 warned.</p></div>
1009 <div class="ulist"><ul>
1010 <li>
1012 Remove the original refs backed up by git-filter-branch: say <tt>git
1013 for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git
1014 update-ref -d</tt>.
1015 </p>
1016 </li>
1017 <li>
1019 Expire all reflogs with <tt>git reflog expire --expire=now --all</tt>.
1020 </p>
1021 </li>
1022 <li>
1024 Garbage collect all unreferenced objects with <tt>git gc --prune=now</tt>
1025 (or if your git-gc is not new enough to support arguments to
1026 <tt>--prune</tt>, use <tt>git repack -ad; git prune</tt> instead).
1027 </p>
1028 </li>
1029 </ul></div>
1030 </div>
1031 <h2 id="_git">GIT</h2>
1032 <div class="sectionbody">
1033 <div class="paragraph"><p>Part of the <a href="git.html">git(1)</a> suite</p></div>
1034 </div>
1035 </div>
1036 <div id="footnotes"><hr /></div>
1037 <div id="footer">
1038 <div id="footer-text">
1039 Last updated 2011-09-21 23:01:14 PDT
1040 </div>
1041 </div>
1042 </body>
1043 </html>