From: Elijah Newren <newren@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Derrick Stolee" <stolee@gmail.com>, "Eric Wong" <e@80x24.org>,
"Jeff King" <peff@peff.net>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"Lars Schneider" <larsxschneider@gmail.com>,
"Jonathan Nieder" <jrnieder@gmail.com>,
"Elijah Newren" <newren@gmail.com>
Subject: [RFC PATCH v2 4/4] Remove git-filter-branch, it is now external to git.git
Date: Tue, 27 Aug 2019 17:22:10 -0700 [thread overview]
Message-ID: <20190828002210.8862-5-newren@gmail.com> (raw)
In-Reply-To: <20190828002210.8862-1-newren@gmail.com>
git-filter-branch still exists, still has the same regression tests,
etc., but it is now being tracked in a separate repo that users will
need to download separately.
Signed-off-by: Elijah Newren <newren@gmail.com>
---
.gitignore | 1 -
Documentation/git-filter-branch.txt | 464 -------------------
Makefile | 1 -
command-list.txt | 1 -
git-filter-branch.sh | 675 ----------------------------
t/perf/p7000-filter-branch.sh | 24 -
t/t7003-filter-branch.sh | 505 ---------------------
t/t7009-filter-branch-null-sha1.sh | 55 ---
t/t9902-completion.sh | 12 +-
9 files changed, 6 insertions(+), 1732 deletions(-)
delete mode 100644 Documentation/git-filter-branch.txt
delete mode 100644 git-filter-branch.sh
delete mode 100755 t/perf/p7000-filter-branch.sh
delete mode 100755 t/t7003-filter-branch.sh
delete mode 100755 t/t7009-filter-branch-null-sha1.sh
diff --git a/.gitignore b/.gitignore
index 521d8f4fb4..97f5d8afea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,7 +63,6 @@
/git-fast-import
/git-fetch
/git-fetch-pack
-/git-filter-branch
/git-fmt-merge-msg
/git-for-each-ref
/git-format-patch
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
deleted file mode 100644
index e4047d472e..0000000000
--- a/Documentation/git-filter-branch.txt
+++ /dev/null
@@ -1,464 +0,0 @@
-git-filter-branch(1)
-====================
-
-NAME
-----
-git-filter-branch - Rewrite branches
-
-SYNOPSIS
---------
-[verse]
-'git filter-branch' [--setup <command>] [--subdirectory-filter <directory>]
- [--env-filter <command>] [--tree-filter <command>]
- [--index-filter <command>] [--parent-filter <command>]
- [--msg-filter <command>] [--commit-filter <command>]
- [--tag-name-filter <command>] [--prune-empty]
- [--original <namespace>] [-d <directory>] [-f | --force]
- [--state-branch <branch>] [--] [<rev-list options>...]
-
-WARNING
--------
-'git filter-branch' has a plethora of pitfalls that can produce non-obvious
-manglings of the intended history rewrite (and can leave you with little
-time to investigate such problems since it has such abysmal performance).
-These safety and performance issues cannot be backward compatibly fixed and
-as such, its use is not recommended. Please use an alternative history
-filtering tool such as https://github.com/newren/git-filter-repo/[git
-filter-repo]. If you still need to use 'git filter-branch', please
-carefully read the "Safety" section of the message on the Git mailing list
-https://public-inbox.org/git/CABPp-BEDOH-row-hxY4u_cP30ptqOpcCvPibwyZ2wBu142qUbA@mail.gmail.com/[detailing
-the land mines of filter-branch] and vigilantly avoid as many of the
-hazards listed there as reasonably possible.
-
-DESCRIPTION
------------
-Lets you rewrite Git revision history by rewriting the branches mentioned
-in the <rev-list options>, applying custom filters on each revision.
-Those filters can modify each tree (e.g. removing a file or running
-a perl rewrite on all files) or information about each commit.
-Otherwise, all information (including original commit times or merge
-information) will be preserved.
-
-The command will only rewrite the _positive_ refs mentioned in the
-command line (e.g. if you pass 'a..b', only 'b' will be rewritten).
-If you specify no filters, the commits will be recommitted without any
-changes, which would normally have no effect. Nevertheless, this may be
-useful in the future for compensating for some Git bugs or such,
-therefore such a usage is permitted.
-
-*NOTE*: This command honors `.git/info/grafts` file and refs in
-the `refs/replace/` namespace.
-If you have any grafts or replacement refs defined, running this command
-will make them permanent.
-
-*WARNING*! The rewritten history will have different object names for all
-the objects and will not converge with the original branch. You will not
-be able to easily push and distribute the rewritten branch on top of the
-original branch. Please do not use this command if you do not know the
-full implications, and avoid using it anyway, if a simple single commit
-would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM
-REBASE" section in linkgit:git-rebase[1] for further information about
-rewriting published history.)
-
-Always verify that the rewritten version is correct: The original refs,
-if different from the rewritten ones, will be stored in the namespace
-'refs/original/'.
-
-Note that since this operation is very I/O expensive, it might
-be a good idea to redirect the temporary directory off-disk with the
-`-d` option, e.g. on tmpfs. Reportedly the speedup is very noticeable.
-
-
-Filters
-~~~~~~~
-
-The filters are applied in the order as listed below. The <command>
-argument is always evaluated in the shell context using the 'eval' command
-(with the notable exception of the commit filter, for technical reasons).
-Prior to that, the `$GIT_COMMIT` environment variable will be set to contain
-the id of the commit being rewritten. Also, GIT_AUTHOR_NAME,
-GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL,
-and GIT_COMMITTER_DATE are taken from the current commit and exported to
-the environment, in order to affect the author and committer identities of
-the replacement commit created by linkgit:git-commit-tree[1] after the
-filters have run.
-
-If any evaluation of <command> returns a non-zero exit status, the whole
-operation will be aborted.
-
-A 'map' function is available that takes an "original sha1 id" argument
-and outputs a "rewritten sha1 id" if the commit has been already
-rewritten, and "original sha1 id" otherwise; the 'map' function can
-return several ids on separate lines if your commit filter emitted
-multiple commits.
-
-
-OPTIONS
--------
-
---setup <command>::
- This is not a real filter executed for each commit but a one
- time setup just before the loop. Therefore no commit-specific
- variables are defined yet. Functions or variables defined here
- can be used or modified in the following filter steps except
- the commit filter, for technical reasons.
-
---subdirectory-filter <directory>::
- Only look at the history which touches the given subdirectory.
- The result will contain that directory (and only that) as its
- project root. Implies <<Remap_to_ancestor>>.
-
---env-filter <command>::
- This filter may be used if you only need to modify the environment
- in which the commit will be performed. Specifically, you might
- want to rewrite the author/committer name/email/time environment
- variables (see linkgit:git-commit-tree[1] for details).
-
---tree-filter <command>::
- This is the filter for rewriting the tree and its contents.
- The argument is evaluated in shell with the working
- directory set to the root of the checked out tree. The new tree
- is then used as-is (new files are auto-added, disappeared files
- are auto-removed - neither .gitignore files nor any other ignore
- rules *HAVE ANY EFFECT*!).
-
---index-filter <command>::
- This is the filter for rewriting the index. It is similar to the
- tree filter but does not check out the tree, which makes it much
- faster. Frequently used with `git rm --cached
- --ignore-unmatch ...`, see EXAMPLES below. For hairy
- cases, see linkgit:git-update-index[1].
-
---parent-filter <command>::
- This is the filter for rewriting the commit's parent list.
- It will receive the parent string on stdin and shall output
- the new parent string on stdout. The parent string is in
- the format described in linkgit:git-commit-tree[1]: empty for
- the initial commit, "-p parent" for a normal commit and
- "-p parent1 -p parent2 -p parent3 ..." for a merge commit.
-
---msg-filter <command>::
- This is the filter for rewriting the commit messages.
- The argument is evaluated in the shell with the original
- commit message on standard input; its standard output is
- used as the new commit message.
-
---commit-filter <command>::
- This is the filter for performing the commit.
- If this filter is specified, it will be called instead of the
- 'git commit-tree' command, with arguments of the form
- "<TREE_ID> [(-p <PARENT_COMMIT_ID>)...]" and the log message on
- stdin. The commit id is expected on stdout.
-+
-As a special extension, the commit filter may emit multiple
-commit ids; in that case, the rewritten children of the original commit will
-have all of them as parents.
-+
-You can use the 'map' convenience function in this filter, and other
-convenience functions, too. For example, calling 'skip_commit "$@"'
-will leave out the current commit (but not its changes! If you want
-that, use 'git rebase' instead).
-+
-You can also use the `git_commit_non_empty_tree "$@"` instead of
-`git commit-tree "$@"` if you don't wish to keep commits with a single parent
-and that makes no change to the tree.
-
---tag-name-filter <command>::
- This is the filter for rewriting tag names. When passed,
- it will be called for every tag ref that points to a rewritten
- object (or to a tag object which points to a rewritten object).
- The original tag name is passed via standard input, and the new
- tag name is expected on standard output.
-+
-The original tags are not deleted, but can be overwritten;
-use "--tag-name-filter cat" to simply update the tags. In this
-case, be very careful and make sure you have the old tags
-backed up in case the conversion has run afoul.
-+
-Nearly proper rewriting of tag objects is supported. If the tag has
-a message attached, a new tag object will be created with the same message,
-author, and timestamp. If the tag has a signature attached, the
-signature will be stripped. It is by definition impossible to preserve
-signatures. The reason this is "nearly" proper, is because ideally if
-the tag did not change (points to the same object, has the same name, etc.)
-it should retain any signature. That is not the case, signatures will always
-be removed, buyer beware. There is also no support for changing the
-author or timestamp (or the tag message for that matter). Tags which point
-to other tags will be rewritten to point to the underlying commit.
-
---prune-empty::
- Some filters will generate empty commits that leave the tree untouched.
- This option instructs git-filter-branch to remove such commits if they
- have exactly one or zero non-pruned parents; merge commits will
- therefore remain intact. This option cannot be used together with
- `--commit-filter`, though the same effect can be achieved by using the
- provided `git_commit_non_empty_tree` function in a commit filter.
-
---original <namespace>::
- Use this option to set the namespace where the original commits
- will be stored. The default value is 'refs/original'.
-
--d <directory>::
- Use this option to set the path to the temporary directory used for
- rewriting. When applying a tree filter, the command needs to
- temporarily check out the tree to some directory, which may consume
- considerable space in case of large projects. By default it
- does this in the `.git-rewrite/` directory but you can override
- that choice by this parameter.
-
--f::
---force::
- 'git filter-branch' refuses to start with an existing temporary
- directory or when there are already refs starting with
- 'refs/original/', unless forced.
-
---state-branch <branch>::
- This option will cause the mapping from old to new objects to
- be loaded from named branch upon startup and saved as a new
- commit to that branch upon exit, enabling incremental of large
- trees. If '<branch>' does not exist it will be created.
-
-<rev-list options>...::
- Arguments for 'git rev-list'. All positive refs included by
- these options are rewritten. You may also specify options
- such as `--all`, but you must use `--` to separate them from
- the 'git filter-branch' options. Implies <<Remap_to_ancestor>>.
-
-
-[[Remap_to_ancestor]]
-Remap to ancestor
-~~~~~~~~~~~~~~~~~
-
-By using linkgit:git-rev-list[1] arguments, e.g., path limiters, you can limit the
-set of revisions which get rewritten. However, positive refs on the command
-line are distinguished: we don't let them be excluded by such limiters. For
-this purpose, they are instead rewritten to point at the nearest ancestor that
-was not excluded.
-
-
-EXIT STATUS
------------
-
-On success, the exit status is `0`. If the filter can't find any commits to
-rewrite, the exit status is `2`. On any other error, the exit status may be
-any other non-zero value.
-
-
-EXAMPLES
---------
-
-Suppose you want to remove a file (containing confidential information
-or copyright violation) from all commits:
-
--------------------------------------------------------
-git filter-branch --tree-filter 'rm filename' HEAD
--------------------------------------------------------
-
-However, if the file is absent from the tree of some commit,
-a simple `rm filename` will fail for that tree and commit.
-Thus you may instead want to use `rm -f filename` as the script.
-
-Using `--index-filter` with 'git rm' yields a significantly faster
-version. Like with using `rm filename`, `git rm --cached filename`
-will fail if the file is absent from the tree of a commit. If you
-want to "completely forget" a file, it does not matter when it entered
-history, so we also add `--ignore-unmatch`:
-
---------------------------------------------------------------------------
-git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
---------------------------------------------------------------------------
-
-Now, you will get the rewritten history saved in HEAD.
-
-To rewrite the repository to look as if `foodir/` had been its project
-root, and discard all other history:
-
--------------------------------------------------------
-git filter-branch --subdirectory-filter foodir -- --all
--------------------------------------------------------
-
-Thus you can, e.g., turn a library subdirectory into a repository of
-its own. Note the `--` that separates 'filter-branch' options from
-revision options, and the `--all` to rewrite all branches and tags.
-
-To set a commit (which typically is at the tip of another
-history) to be the parent of the current initial commit, in
-order to paste the other history behind the current history:
-
--------------------------------------------------------------------
-git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD
--------------------------------------------------------------------
-
-(if the parent string is empty - which happens when we are dealing with
-the initial commit - add graftcommit as a parent). Note that this assumes
-history with a single root (that is, no merge without common ancestors
-happened). If this is not the case, use:
-
---------------------------------------------------------------------------
-git filter-branch --parent-filter \
- 'test $GIT_COMMIT = <commit-id> && echo "-p <graft-id>" || cat' HEAD
---------------------------------------------------------------------------
-
-or even simpler:
-
------------------------------------------------
-git replace --graft $commit-id $graft-id
-git filter-branch $graft-id..HEAD
------------------------------------------------
-
-To remove commits authored by "Darl McBribe" from the history:
-
-------------------------------------------------------------------------------
-git filter-branch --commit-filter '
- if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
- then
- skip_commit "$@";
- else
- git commit-tree "$@";
- fi' HEAD
-------------------------------------------------------------------------------
-
-The function 'skip_commit' is defined as follows:
-
---------------------------
-skip_commit()
-{
- shift;
- while [ -n "$1" ];
- do
- shift;
- map "$1";
- shift;
- done;
-}
---------------------------
-
-The shift magic first throws away the tree id and then the -p
-parameters. Note that this handles merges properly! In case Darl
-committed a merge between P1 and P2, it will be propagated properly
-and all children of the merge will become merge commits with P1,P2
-as their parents instead of the merge commit.
-
-*NOTE* the changes introduced by the commits, and which are not reverted
-by subsequent commits, will still be in the rewritten branch. If you want
-to throw out _changes_ together with the commits, you should use the
-interactive mode of 'git rebase'.
-
-You can rewrite the commit log messages using `--msg-filter`. For
-example, 'git svn-id' strings in a repository created by 'git svn' can
-be removed this way:
-
--------------------------------------------------------
-git filter-branch --msg-filter '
- sed -e "/^git-svn-id:/d"
-'
--------------------------------------------------------
-
-If you need to add 'Acked-by' lines to, say, the last 10 commits (none
-of which is a merge), use this command:
-
---------------------------------------------------------
-git filter-branch --msg-filter '
- cat &&
- echo "Acked-by: Bugs Bunny <bunny@bugzilla.org>"
-' HEAD~10..HEAD
---------------------------------------------------------
-
-The `--env-filter` option can be used to modify committer and/or author
-identity. For example, if you found out that your commits have the wrong
-identity due to a misconfigured user.email, you can make a correction,
-before publishing the project, like this:
-
---------------------------------------------------------
-git filter-branch --env-filter '
- if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
- then
- GIT_AUTHOR_EMAIL=john@example.com
- fi
- if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
- then
- GIT_COMMITTER_EMAIL=john@example.com
- fi
-' -- --all
---------------------------------------------------------
-
-To restrict rewriting to only part of the history, specify a revision
-range in addition to the new branch name. The new branch name will
-point to the top-most revision that a 'git rev-list' of this range
-will print.
-
-Consider this history:
-
-------------------
- D--E--F--G--H
- / /
-A--B-----C
-------------------
-
-To rewrite only commits D,E,F,G,H, but leave A, B and C alone, use:
-
---------------------------------
-git filter-branch ... C..H
---------------------------------
-
-To rewrite commits E,F,G,H, use one of these:
-
-----------------------------------------
-git filter-branch ... C..H --not D
-git filter-branch ... D..H --not C
-----------------------------------------
-
-To move the whole tree into a subdirectory, or remove it from there:
-
----------------------------------------------------------------
-git filter-branch --index-filter \
- 'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
- GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
- git update-index --index-info &&
- mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
----------------------------------------------------------------
-
-
-
-CHECKLIST FOR SHRINKING A REPOSITORY
-------------------------------------
-
-git-filter-branch can be used to get rid of a subset of files,
-usually with some combination of `--index-filter` and
-`--subdirectory-filter`. People expect the resulting repository to
-be smaller than the original, but you need a few more steps to
-actually make it smaller, because Git tries hard not to lose your
-objects until you tell it to. First make sure that:
-
-* You really removed all variants of a filename, if a blob was moved
- over its lifetime. `git log --name-only --follow --all -- filename`
- can help you find renames.
-
-* You really filtered all refs: use `--tag-name-filter cat -- --all`
- when calling git-filter-branch.
-
-Then there are two ways to get a smaller repository. A safer way is
-to clone, that keeps your original intact.
-
-* Clone it with `git clone file:///path/to/repo`. The clone
- will not have the removed objects. See linkgit:git-clone[1]. (Note
- that cloning with a plain path just hardlinks everything!)
-
-If you really don't want to clone it, for whatever reasons, check the
-following points instead (in this order). This is a very destructive
-approach, so *make a backup* or go back to cloning it. You have been
-warned.
-
-* Remove the original refs backed up by git-filter-branch: say `git
- for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git
- update-ref -d`.
-
-* Expire all reflogs with `git reflog expire --expire=now --all`.
-
-* Garbage collect all unreferenced objects with `git gc --prune=now`
- (or if your git-gc is not new enough to support arguments to
- `--prune`, use `git repack -ad; git prune` instead).
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Makefile b/Makefile
index f9255344ae..20850def5d 100644
--- a/Makefile
+++ b/Makefile
@@ -607,7 +607,6 @@ unexport CDPATH
SCRIPT_SH += git-bisect.sh
SCRIPT_SH += git-difftool--helper.sh
-SCRIPT_SH += git-filter-branch.sh
SCRIPT_SH += git-merge-octopus.sh
SCRIPT_SH += git-merge-one-file.sh
SCRIPT_SH += git-merge-resolve.sh
diff --git a/command-list.txt b/command-list.txt
index a9ac72bef4..1ba65d9516 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -90,7 +90,6 @@ git-fast-export ancillarymanipulators
git-fast-import ancillarymanipulators
git-fetch mainporcelain remote
git-fetch-pack synchingrepositories
-git-filter-branch ancillarymanipulators
git-fmt-merge-msg purehelpers
git-for-each-ref plumbinginterrogators
git-format-patch mainporcelain
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
deleted file mode 100644
index 7b1865c1d5..0000000000
--- a/git-filter-branch.sh
+++ /dev/null
@@ -1,675 +0,0 @@
-#!/bin/sh
-#
-# Rewrite revision history
-# Copyright (c) Petr Baudis, 2006
-# Minimal changes to "port" it to core-git (c) Johannes Schindelin, 2007
-#
-# Lets you rewrite the revision history of the current branch, creating
-# a new branch. You can specify a number of filters to modify the commits,
-# files and trees.
-
-# The following functions will also be available in the commit filter:
-
-functions=$(cat << \EOF
-EMPTY_TREE=$(git hash-object -t tree /dev/null)
-
-warn () {
- echo "$*" >&2
-}
-
-map()
-{
- # if it was not rewritten, take the original
- if test -r "$workdir/../map/$1"
- then
- cat "$workdir/../map/$1"
- else
- echo "$1"
- fi
-}
-
-# if you run 'skip_commit "$@"' in a commit filter, it will print
-# the (mapped) parents, effectively skipping the commit.
-
-skip_commit()
-{
- shift;
- while [ -n "$1" ];
- do
- shift;
- map "$1";
- shift;
- done;
-}
-
-# if you run 'git_commit_non_empty_tree "$@"' in a commit filter,
-# it will skip commits that leave the tree untouched, commit the other.
-git_commit_non_empty_tree()
-{
- if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
- map "$3"
- elif test $# = 1 && test "$1" = $EMPTY_TREE; then
- :
- else
- git commit-tree "$@"
- fi
-}
-# override die(): this version puts in an extra line break, so that
-# the progress is still visible
-
-die()
-{
- echo >&2
- echo "$*" >&2
- exit 1
-}
-EOF
-)
-
-eval "$functions"
-
-finish_ident() {
- # Ensure non-empty id name.
- echo "case \"\$GIT_$1_NAME\" in \"\") GIT_$1_NAME=\"\${GIT_$1_EMAIL%%@*}\" && export GIT_$1_NAME;; esac"
- # And make sure everything is exported.
- echo "export GIT_$1_NAME"
- echo "export GIT_$1_EMAIL"
- echo "export GIT_$1_DATE"
-}
-
-set_ident () {
- parse_ident_from_commit author AUTHOR committer COMMITTER
- finish_ident AUTHOR
- finish_ident COMMITTER
-}
-
-if [ -z "$FILTER_BRANCH_SQUELCH_WARNING" -a \
- -z "$GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS" ]; then
- cat <<EOF
-WARNING: git-filter-branch has a glut of gotchas generating mangled history
- rewrites. Please use an alternative filtering tool such as 'git
- filter-repo' (https://github.com/newren/git-filter-repo/) instead.
- See the filter-branch manual page for more details; to squelch
- this warning and pause, set FILTER_BRANCH_SQUELCH_WARNING=1.
-
-EOF
- sleep 5
-fi
-
-USAGE="[--setup <command>] [--subdirectory-filter <directory>] [--env-filter <command>]
- [--tree-filter <command>] [--index-filter <command>]
- [--parent-filter <command>] [--msg-filter <command>]
- [--commit-filter <command>] [--tag-name-filter <command>]
- [--original <namespace>]
- [-d <directory>] [-f | --force] [--state-branch <branch>]
- [--] [<rev-list options>...]"
-
-OPTIONS_SPEC=
-. git-sh-setup
-
-if [ "$(is_bare_repository)" = false ]; then
- require_clean_work_tree 'rewrite branches'
-fi
-
-tempdir=.git-rewrite
-filter_setup=
-filter_env=
-filter_tree=
-filter_index=
-filter_parent=
-filter_msg=cat
-filter_commit=
-filter_tag_name=
-filter_subdir=
-state_branch=
-orig_namespace=refs/original/
-force=
-prune_empty=
-remap_to_ancestor=
-while :
-do
- case "$1" in
- --)
- shift
- break
- ;;
- --force|-f)
- shift
- force=t
- continue
- ;;
- --remap-to-ancestor)
- # deprecated ($remap_to_ancestor is set now automatically)
- shift
- remap_to_ancestor=t
- continue
- ;;
- --prune-empty)
- shift
- prune_empty=t
- continue
- ;;
- -*)
- ;;
- *)
- break;
- esac
-
- # all switches take one argument
- ARG="$1"
- case "$#" in 1) usage ;; esac
- shift
- OPTARG="$1"
- shift
-
- case "$ARG" in
- -d)
- tempdir="$OPTARG"
- ;;
- --setup)
- filter_setup="$OPTARG"
- ;;
- --subdirectory-filter)
- filter_subdir="$OPTARG"
- remap_to_ancestor=t
- ;;
- --env-filter)
- filter_env="$OPTARG"
- ;;
- --tree-filter)
- filter_tree="$OPTARG"
- ;;
- --index-filter)
- filter_index="$OPTARG"
- ;;
- --parent-filter)
- filter_parent="$OPTARG"
- ;;
- --msg-filter)
- filter_msg="$OPTARG"
- ;;
- --commit-filter)
- filter_commit="$functions; $OPTARG"
- ;;
- --tag-name-filter)
- filter_tag_name="$OPTARG"
- ;;
- --original)
- orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
- ;;
- --state-branch)
- state_branch="$OPTARG"
- ;;
- *)
- usage
- ;;
- esac
-done
-
-case "$prune_empty,$filter_commit" in
-,)
- filter_commit='git commit-tree "$@"';;
-t,)
- filter_commit="$functions;"' git_commit_non_empty_tree "$@"';;
-,*)
- ;;
-*)
- die "Cannot set --prune-empty and --commit-filter at the same time"
-esac
-
-case "$force" in
-t)
- rm -rf "$tempdir"
-;;
-'')
- test -d "$tempdir" &&
- die "$tempdir already exists, please remove it"
-esac
-orig_dir=$(pwd)
-mkdir -p "$tempdir/t" &&
-tempdir="$(cd "$tempdir"; pwd)" &&
-cd "$tempdir/t" &&
-workdir="$(pwd)" ||
-die ""
-
-# Remove tempdir on exit
-trap 'cd "$orig_dir"; rm -rf "$tempdir"' 0
-
-ORIG_GIT_DIR="$GIT_DIR"
-ORIG_GIT_WORK_TREE="$GIT_WORK_TREE"
-ORIG_GIT_INDEX_FILE="$GIT_INDEX_FILE"
-ORIG_GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME"
-ORIG_GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL"
-ORIG_GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE"
-ORIG_GIT_COMMITTER_NAME="$GIT_COMMITTER_NAME"
-ORIG_GIT_COMMITTER_EMAIL="$GIT_COMMITTER_EMAIL"
-ORIG_GIT_COMMITTER_DATE="$GIT_COMMITTER_DATE"
-
-GIT_WORK_TREE=.
-export GIT_DIR GIT_WORK_TREE
-
-# Make sure refs/original is empty
-git for-each-ref > "$tempdir"/backup-refs || exit
-while read sha1 type name
-do
- case "$force,$name" in
- ,$orig_namespace*)
- die "Cannot create a new backup.
-A previous backup already exists in $orig_namespace
-Force overwriting the backup with -f"
- ;;
- t,$orig_namespace*)
- git update-ref -d "$name" $sha1
- ;;
- esac
-done < "$tempdir"/backup-refs
-
-# The refs should be updated if their heads were rewritten
-git rev-parse --no-flags --revs-only --symbolic-full-name \
- --default HEAD "$@" > "$tempdir"/raw-refs || exit
-while read ref
-do
- case "$ref" in ^?*) continue ;; esac
-
- if git rev-parse --verify "$ref"^0 >/dev/null 2>&1
- then
- echo "$ref"
- else
- warn "WARNING: not rewriting '$ref' (not a committish)"
- fi
-done >"$tempdir"/heads <"$tempdir"/raw-refs
-
-test -s "$tempdir"/heads ||
- die "You must specify a ref to rewrite."
-
-GIT_INDEX_FILE="$(pwd)/../index"
-export GIT_INDEX_FILE
-
-# map old->new commit ids for rewriting parents
-mkdir ../map || die "Could not create map/ directory"
-
-if test -n "$state_branch"
-then
- state_commit=$(git rev-parse --no-flags --revs-only "$state_branch")
- if test -n "$state_commit"
- then
- echo "Populating map from $state_branch ($state_commit)" 1>&2
- perl -e'open(MAP, "-|", "git show $ARGV[0]:filter.map") or die;
- while (<MAP>) {
- m/(.*):(.*)/ or die;
- open F, ">../map/$1" or die;
- print F "$2" or die;
- close(F) or die;
- }
- close(MAP) or die;' "$state_commit" \
- || die "Unable to load state from $state_branch:filter.map"
- else
- echo "Branch $state_branch does not exist. Will create" 1>&2
- fi
-fi
-
-# we need "--" only if there are no path arguments in $@
-nonrevs=$(git rev-parse --no-revs "$@") || exit
-if test -z "$nonrevs"
-then
- dashdash=--
-else
- dashdash=
- remap_to_ancestor=t
-fi
-
-git rev-parse --revs-only "$@" >../parse
-
-case "$filter_subdir" in
-"")
- eval set -- "$(git rev-parse --sq --no-revs "$@")"
- ;;
-*)
- eval set -- "$(git rev-parse --sq --no-revs "$@" $dashdash \
- "$filter_subdir")"
- ;;
-esac
-
-git rev-list --reverse --topo-order --default HEAD \
- --parents --simplify-merges --stdin "$@" <../parse >../revs ||
- die "Could not get the commits"
-commits=$(wc -l <../revs | tr -d " ")
-
-test $commits -eq 0 && die_with_status 2 "Found nothing to rewrite"
-
-# Rewrite the commits
-report_progress ()
-{
- if test -n "$progress" &&
- test $git_filter_branch__commit_count -gt $next_sample_at
- then
- count=$git_filter_branch__commit_count
-
- now=$(date +%s)
- elapsed=$(($now - $start_timestamp))
- remaining=$(( ($commits - $count) * $elapsed / $count ))
- if test $elapsed -gt 0
- then
- next_sample_at=$(( ($elapsed + 1) * $count / $elapsed ))
- else
- next_sample_at=$(($next_sample_at + 1))
- fi
- progress=" ($elapsed seconds passed, remaining $remaining predicted)"
- fi
- printf "\rRewrite $commit ($count/$commits)$progress "
-}
-
-git_filter_branch__commit_count=0
-
-progress= start_timestamp=
-if date '+%s' 2>/dev/null | grep -q '^[0-9][0-9]*$'
-then
- next_sample_at=0
- progress="dummy to ensure this is not empty"
- start_timestamp=$(date '+%s')
-fi
-
-if test -n "$filter_index" ||
- test -n "$filter_tree" ||
- test -n "$filter_subdir"
-then
- need_index=t
-else
- need_index=
-fi
-
-eval "$filter_setup" < /dev/null ||
- die "filter setup failed: $filter_setup"
-
-while read commit parents; do
- git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
-
- report_progress
- test -f "$workdir"/../map/$commit && continue
-
- case "$filter_subdir" in
- "")
- if test -n "$need_index"
- then
- GIT_ALLOW_NULL_SHA1=1 git read-tree -i -m $commit
- fi
- ;;
- *)
- # The commit may not have the subdirectory at all
- err=$(GIT_ALLOW_NULL_SHA1=1 \
- git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
- if ! git rev-parse -q --verify $commit:"$filter_subdir"
- then
- rm -f "$GIT_INDEX_FILE"
- else
- echo >&2 "$err"
- false
- fi
- }
- esac || die "Could not initialize the index"
-
- GIT_COMMIT=$commit
- export GIT_COMMIT
- git cat-file commit "$commit" >../commit ||
- die "Cannot read commit $commit"
-
- eval "$(set_ident <../commit)" ||
- die "setting author/committer failed for commit $commit"
- eval "$filter_env" < /dev/null ||
- die "env filter failed: $filter_env"
-
- if [ "$filter_tree" ]; then
- git checkout-index -f -u -a ||
- die "Could not checkout the index"
- # files that $commit removed are now still in the working tree;
- # remove them, else they would be added again
- git clean -d -q -f -x
- eval "$filter_tree" < /dev/null ||
- die "tree filter failed: $filter_tree"
-
- (
- git diff-index -r --name-only --ignore-submodules $commit -- &&
- git ls-files --others
- ) > "$tempdir"/tree-state || exit
- git update-index --add --replace --remove --stdin \
- < "$tempdir"/tree-state || exit
- fi
-
- eval "$filter_index" < /dev/null ||
- die "index filter failed: $filter_index"
-
- parentstr=
- for parent in $parents; do
- for reparent in $(map "$parent"); do
- case "$parentstr " in
- *" -p $reparent "*)
- ;;
- *)
- parentstr="$parentstr -p $reparent"
- ;;
- esac
- done
- done
- if [ "$filter_parent" ]; then
- parentstr="$(echo "$parentstr" | eval "$filter_parent")" ||
- die "parent filter failed: $filter_parent"
- fi
-
- {
- while IFS='' read -r header_line && test -n "$header_line"
- do
- # skip header lines...
- :;
- done
- # and output the actual commit message
- cat
- } <../commit |
- eval "$filter_msg" > ../message ||
- die "msg filter failed: $filter_msg"
-
- if test -n "$need_index"
- then
- tree=$(git write-tree)
- else
- tree=$(git rev-parse "$commit^{tree}")
- fi
- workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
- "$tree" $parentstr < ../message > ../map/$commit ||
- die "could not write rewritten commit"
-done <../revs
-
-# If we are filtering for paths, as in the case of a subdirectory
-# filter, it is possible that a specified head is not in the set of
-# rewritten commits, because it was pruned by the revision walker.
-# Ancestor remapping fixes this by mapping these heads to the unique
-# nearest ancestor that survived the pruning.
-
-if test "$remap_to_ancestor" = t
-then
- while read ref
- do
- sha1=$(git rev-parse "$ref"^0)
- test -f "$workdir"/../map/$sha1 && continue
- ancestor=$(git rev-list --simplify-merges -1 "$ref" "$@")
- test "$ancestor" && echo $(map $ancestor) >> "$workdir"/../map/$sha1
- done < "$tempdir"/heads
-fi
-
-# Finally update the refs
-
-_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
-echo
-while read ref
-do
- # avoid rewriting a ref twice
- test -f "$orig_namespace$ref" && continue
-
- sha1=$(git rev-parse "$ref"^0)
- rewritten=$(map $sha1)
-
- test $sha1 = "$rewritten" &&
- warn "WARNING: Ref '$ref' is unchanged" &&
- continue
-
- case "$rewritten" in
- '')
- echo "Ref '$ref' was deleted"
- git update-ref -m "filter-branch: delete" -d "$ref" $sha1 ||
- die "Could not delete $ref"
- ;;
- $_x40)
- echo "Ref '$ref' was rewritten"
- if ! git update-ref -m "filter-branch: rewrite" \
- "$ref" $rewritten $sha1 2>/dev/null; then
- if test $(git cat-file -t "$ref") = tag; then
- if test -z "$filter_tag_name"; then
- warn "WARNING: You said to rewrite tagged commits, but not the corresponding tag."
- warn "WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag."
- fi
- else
- die "Could not rewrite $ref"
- fi
- fi
- ;;
- *)
- # NEEDSWORK: possibly add -Werror, making this an error
- warn "WARNING: '$ref' was rewritten into multiple commits:"
- warn "$rewritten"
- warn "WARNING: Ref '$ref' points to the first one now."
- rewritten=$(echo "$rewritten" | head -n 1)
- git update-ref -m "filter-branch: rewrite to first" \
- "$ref" $rewritten $sha1 ||
- die "Could not rewrite $ref"
- ;;
- esac
- git update-ref -m "filter-branch: backup" "$orig_namespace$ref" $sha1 ||
- exit
-done < "$tempdir"/heads
-
-# TODO: This should possibly go, with the semantics that all positive given
-# refs are updated, and their original heads stored in refs/original/
-# Filter tags
-
-if [ "$filter_tag_name" ]; then
- git for-each-ref --format='%(objectname) %(objecttype) %(refname)' refs/tags |
- while read sha1 type ref; do
- ref="${ref#refs/tags/}"
- # XXX: Rewrite tagged trees as well?
- if [ "$type" != "commit" -a "$type" != "tag" ]; then
- continue;
- fi
-
- if [ "$type" = "tag" ]; then
- # Dereference to a commit
- sha1t="$sha1"
- sha1="$(git rev-parse -q "$sha1"^{commit})" || continue
- fi
-
- [ -f "../map/$sha1" ] || continue
- new_sha1="$(cat "../map/$sha1")"
- GIT_COMMIT="$sha1"
- export GIT_COMMIT
- new_ref="$(echo "$ref" | eval "$filter_tag_name")" ||
- die "tag name filter failed: $filter_tag_name"
-
- echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
-
- if [ "$type" = "tag" ]; then
- new_sha1=$( ( printf 'object %s\ntype commit\ntag %s\n' \
- "$new_sha1" "$new_ref"
- git cat-file tag "$ref" |
- sed -n \
- -e '1,/^$/{
- /^object /d
- /^type /d
- /^tag /d
- }' \
- -e '/^-----BEGIN PGP SIGNATURE-----/q' \
- -e 'p' ) |
- git hash-object -t tag -w --stdin) ||
- die "Could not create new tag object for $ref"
- if git cat-file tag "$ref" | \
- sane_grep '^-----BEGIN PGP SIGNATURE-----' >/dev/null 2>&1
- then
- warn "gpg signature stripped from tag object $sha1t"
- fi
- fi
-
- git update-ref "refs/tags/$new_ref" "$new_sha1" ||
- die "Could not write tag $new_ref"
- done
-fi
-
-unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
-unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
-unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
-test -z "$ORIG_GIT_DIR" || {
- GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
-}
-test -z "$ORIG_GIT_WORK_TREE" || {
- GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
- export GIT_WORK_TREE
-}
-test -z "$ORIG_GIT_INDEX_FILE" || {
- GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
- export GIT_INDEX_FILE
-}
-test -z "$ORIG_GIT_AUTHOR_NAME" || {
- GIT_AUTHOR_NAME="$ORIG_GIT_AUTHOR_NAME" &&
- export GIT_AUTHOR_NAME
-}
-test -z "$ORIG_GIT_AUTHOR_EMAIL" || {
- GIT_AUTHOR_EMAIL="$ORIG_GIT_AUTHOR_EMAIL" &&
- export GIT_AUTHOR_EMAIL
-}
-test -z "$ORIG_GIT_AUTHOR_DATE" || {
- GIT_AUTHOR_DATE="$ORIG_GIT_AUTHOR_DATE" &&
- export GIT_AUTHOR_DATE
-}
-test -z "$ORIG_GIT_COMMITTER_NAME" || {
- GIT_COMMITTER_NAME="$ORIG_GIT_COMMITTER_NAME" &&
- export GIT_COMMITTER_NAME
-}
-test -z "$ORIG_GIT_COMMITTER_EMAIL" || {
- GIT_COMMITTER_EMAIL="$ORIG_GIT_COMMITTER_EMAIL" &&
- export GIT_COMMITTER_EMAIL
-}
-test -z "$ORIG_GIT_COMMITTER_DATE" || {
- GIT_COMMITTER_DATE="$ORIG_GIT_COMMITTER_DATE" &&
- export GIT_COMMITTER_DATE
-}
-
-if test -n "$state_branch"
-then
- echo "Saving rewrite state to $state_branch" 1>&2
- state_blob=$(
- perl -e'opendir D, "../map" or die;
- open H, "|-", "git hash-object -w --stdin" or die;
- foreach (sort readdir(D)) {
- next if m/^\.\.?$/;
- open F, "<../map/$_" or die;
- chomp($f = <F>);
- print H "$_:$f\n" or die;
- }
- close(H) or die;' || die "Unable to save state")
- state_tree=$(printf '100644 blob %s\tfilter.map\n' "$state_blob" | git mktree)
- if test -n "$state_commit"
- then
- state_commit=$(echo "Sync" | git commit-tree "$state_tree" -p "$state_commit")
- else
- state_commit=$(echo "Sync" | git commit-tree "$state_tree" )
- fi
- git update-ref "$state_branch" "$state_commit"
-fi
-
-cd "$orig_dir"
-rm -rf "$tempdir"
-
-trap - 0
-
-if [ "$(is_bare_repository)" = false ]; then
- git read-tree -u -m HEAD || exit
-fi
-
-exit 0
diff --git a/t/perf/p7000-filter-branch.sh b/t/perf/p7000-filter-branch.sh
deleted file mode 100755
index b029586ccb..0000000000
--- a/t/perf/p7000-filter-branch.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-test_description='performance of filter-branch'
-. ./perf-lib.sh
-
-test_perf_default_repo
-test_checkout_worktree
-
-test_expect_success 'mark bases for tests' '
- git tag -f tip &&
- git tag -f base HEAD~100
-'
-
-test_perf 'noop filter' '
- git checkout --detach tip &&
- git filter-branch -f base..HEAD
-'
-
-test_perf 'noop prune-empty' '
- git checkout --detach tip &&
- git filter-branch -f --prune-empty base..HEAD
-'
-
-test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
deleted file mode 100755
index e23de7d0b5..0000000000
--- a/t/t7003-filter-branch.sh
+++ /dev/null
@@ -1,505 +0,0 @@
-#!/bin/sh
-
-test_description='git filter-branch'
-. ./test-lib.sh
-. "$TEST_DIRECTORY/lib-gpg.sh"
-
-test_expect_success 'setup' '
- test_commit A &&
- GIT_COMMITTER_DATE="@0 +0000" GIT_AUTHOR_DATE="@0 +0000" &&
- test_commit --notick B &&
- git checkout -b branch B &&
- test_commit D &&
- mkdir dir &&
- test_commit dir/D &&
- test_commit E &&
- git checkout master &&
- test_commit C &&
- git checkout branch &&
- git merge C &&
- git tag F &&
- test_commit G &&
- test_commit H
-'
-# * (HEAD, branch) H
-# * G
-# * Merge commit 'C' into branch
-# |\
-# | * (master) C
-# * | E
-# * | dir/D
-# * | D
-# |/
-# * B
-# * A
-
-
-H=$(git rev-parse H)
-
-test_expect_success 'rewrite identically' '
- git filter-branch branch
-'
-test_expect_success 'result is really identical' '
- test $H = $(git rev-parse HEAD)
-'
-
-test_expect_success 'rewrite bare repository identically' '
- (git config core.bare true && cd .git &&
- git filter-branch branch > filter-output 2>&1 &&
- ! fgrep fatal filter-output)
-'
-git config core.bare false
-test_expect_success 'result is really identical' '
- test $H = $(git rev-parse HEAD)
-'
-
-TRASHDIR=$(pwd)
-test_expect_success 'correct GIT_DIR while using -d' '
- mkdir drepo &&
- ( cd drepo &&
- git init &&
- test_commit drepo &&
- git filter-branch -d "$TRASHDIR/dfoo" \
- --index-filter "cp \"$TRASHDIR\"/dfoo/backup-refs \"$TRASHDIR\"" \
- ) &&
- grep drepo "$TRASHDIR/backup-refs"
-'
-
-test_expect_success 'tree-filter works with -d' '
- git init drepo-tree &&
- (
- cd drepo-tree &&
- test_commit one &&
- git filter-branch -d "$TRASHDIR/dfoo" \
- --tree-filter "echo changed >one.t" &&
- echo changed >expect &&
- git cat-file blob HEAD:one.t >actual &&
- test_cmp expect actual &&
- test_cmp one.t actual
- )
-'
-
-test_expect_success 'Fail if commit filter fails' '
- test_must_fail git filter-branch -f --commit-filter "exit 1" HEAD
-'
-
-test_expect_success 'rewrite, renaming a specific file' '
- git filter-branch -f --tree-filter "mv D.t doh || :" HEAD
-'
-
-test_expect_success 'test that the file was renamed' '
- test D = "$(git show HEAD:doh --)" &&
- ! test -f D.t &&
- test -f doh &&
- test D = "$(cat doh)"
-'
-
-test_expect_success 'rewrite, renaming a specific directory' '
- git filter-branch -f --tree-filter "mv dir diroh || :" HEAD
-'
-
-test_expect_success 'test that the directory was renamed' '
- test dir/D = "$(git show HEAD:diroh/D.t --)" &&
- ! test -d dir &&
- test -d diroh &&
- ! test -d diroh/dir &&
- test -f diroh/D.t &&
- test dir/D = "$(cat diroh/D.t)"
-'
-
-V=$(git rev-parse HEAD)
-
-test_expect_success 'populate --state-branch' '
- git filter-branch --state-branch state -f --tree-filter "touch file || :" HEAD
-'
-
-W=$(git rev-parse HEAD)
-
-test_expect_success 'using --state-branch to skip already rewritten commits' '
- test_when_finished git reset --hard $V &&
- git reset --hard $V &&
- git filter-branch --state-branch state -f --tree-filter "touch file || :" HEAD &&
- test_cmp_rev $W HEAD
-'
-
-git tag oldD HEAD~4
-test_expect_success 'rewrite one branch, keeping a side branch' '
- git branch modD oldD &&
- git filter-branch -f --tree-filter "mv B.t boh || :" D..modD
-'
-
-test_expect_success 'common ancestor is still common (unchanged)' '
- test "$(git merge-base modD D)" = "$(git rev-parse B)"
-'
-
-test_expect_success 'filter subdirectory only' '
- mkdir subdir &&
- touch subdir/new &&
- git add subdir/new &&
- test_tick &&
- git commit -m "subdir" &&
- echo H > A.t &&
- test_tick &&
- git commit -m "not subdir" A.t &&
- echo A > subdir/new &&
- test_tick &&
- git commit -m "again subdir" subdir/new &&
- git rm A.t &&
- test_tick &&
- git commit -m "again not subdir" &&
- git branch sub &&
- git branch sub-earlier HEAD~2 &&
- git filter-branch -f --subdirectory-filter subdir \
- refs/heads/sub refs/heads/sub-earlier
-'
-
-test_expect_success 'subdirectory filter result looks okay' '
- test 2 = $(git rev-list sub | wc -l) &&
- git show sub:new &&
- test_must_fail git show sub:subdir &&
- git show sub-earlier:new &&
- test_must_fail git show sub-earlier:subdir
-'
-
-test_expect_success 'more setup' '
- git checkout master &&
- mkdir subdir &&
- echo A > subdir/new &&
- git add subdir/new &&
- test_tick &&
- git commit -m "subdir on master" subdir/new &&
- git rm A.t &&
- test_tick &&
- git commit -m "again subdir on master" &&
- git merge branch
-'
-
-test_expect_success 'use index-filter to move into a subdirectory' '
- git branch directorymoved &&
- git filter-branch -f --index-filter \
- "git ls-files -s | sed \"s- -&newsubdir/-\" |
- GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \
- git update-index --index-info &&
- mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved &&
- git diff --exit-code HEAD directorymoved:newsubdir
-'
-
-test_expect_success 'stops when msg filter fails' '
- old=$(git rev-parse HEAD) &&
- test_must_fail git filter-branch -f --msg-filter false HEAD &&
- test $old = $(git rev-parse HEAD) &&
- rm -rf .git-rewrite
-'
-
-test_expect_success 'author information is preserved' '
- : > i &&
- git add i &&
- test_tick &&
- GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips &&
- git branch preserved-author &&
- (sane_unset GIT_AUTHOR_NAME &&
- git filter-branch -f --msg-filter "cat; \
- test \$GIT_COMMIT != $(git rev-parse master) || \
- echo Hallo" \
- preserved-author) &&
- git rev-list --author="B V Uips" preserved-author >actual &&
- test_line_count = 1 actual
-'
-
-test_expect_success "remove a certain author's commits" '
- echo i > i &&
- test_tick &&
- git commit -m i i &&
- git branch removed-author &&
- git filter-branch -f --commit-filter "\
- if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\
- then\
- skip_commit \"\$@\";
- else\
- git commit-tree \"\$@\";\
- fi" removed-author &&
- cnt1=$(git rev-list master | wc -l) &&
- cnt2=$(git rev-list removed-author | wc -l) &&
- test $cnt1 -eq $(($cnt2 + 1)) &&
- git rev-list --author="B V Uips" removed-author >actual &&
- test_line_count = 0 actual
-'
-
-test_expect_success 'barf on invalid name' '
- test_must_fail git filter-branch -f master xy-problem &&
- test_must_fail git filter-branch -f HEAD^
-'
-
-test_expect_success '"map" works in commit filter' '
- git filter-branch -f --commit-filter "\
- parent=\$(git rev-parse \$GIT_COMMIT^) &&
- mapped=\$(map \$parent) &&
- actual=\$(echo \"\$@\" | sed \"s/^.*-p //\") &&
- test \$mapped = \$actual &&
- git commit-tree \"\$@\";" master~2..master &&
- git rev-parse --verify master
-'
-
-test_expect_success 'Name needing quotes' '
-
- git checkout -b rerere A &&
- mkdir foo &&
- name="れれれ" &&
- >foo/$name &&
- git add foo &&
- git commit -m "Adding a file" &&
- git filter-branch --tree-filter "rm -fr foo" &&
- test_must_fail git ls-files --error-unmatch "foo/$name" &&
- test $(git rev-parse --verify rerere) != $(git rev-parse --verify A)
-
-'
-
-test_expect_success 'Subdirectory filter with disappearing trees' '
- git reset --hard &&
- git checkout master &&
-
- mkdir foo &&
- touch foo/bar &&
- git add foo &&
- test_tick &&
- git commit -m "Adding foo" &&
-
- git rm -r foo &&
- test_tick &&
- git commit -m "Removing foo" &&
-
- mkdir foo &&
- touch foo/bar &&
- git add foo &&
- test_tick &&
- git commit -m "Re-adding foo" &&
-
- git filter-branch -f --subdirectory-filter foo &&
- git rev-list master >actual &&
- test_line_count = 3 actual
-'
-
-test_expect_success 'Tag name filtering retains tag message' '
- git tag -m atag T &&
- git cat-file tag T > expect &&
- git filter-branch -f --tag-name-filter cat &&
- git cat-file tag T > actual &&
- test_cmp expect actual
-'
-
-faux_gpg_tag='object XXXXXX
-type commit
-tag S
-tagger T A Gger <tagger@example.com> 1206026339 -0500
-
-This is a faux gpg signed tag.
------BEGIN PGP SIGNATURE-----
-Version: FauxGPG v0.0.0 (FAUX/Linux)
-
-gdsfoewhxu/6l06f1kxyxhKdZkrcbaiOMtkJUA9ITAc1mlamh0ooasxkH1XwMbYQ
-acmwXaWET20H0GeAGP+7vow=
-=agpO
------END PGP SIGNATURE-----
-'
-test_expect_success 'Tag name filtering strips gpg signature' '
- sha1=$(git rev-parse HEAD) &&
- sha1t=$(echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | git mktag) &&
- git update-ref "refs/tags/S" "$sha1t" &&
- echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&
- git filter-branch -f --tag-name-filter cat &&
- git cat-file tag S > actual &&
- test_cmp expect actual
-'
-
-test_expect_success GPG 'Filtering retains message of gpg signed commit' '
- mkdir gpg &&
- touch gpg/foo &&
- git add gpg &&
- test_tick &&
- git commit -S -m "Adding gpg" &&
-
- git log -1 --format="%s" > expect &&
- git filter-branch -f --msg-filter "cat" &&
- git log -1 --format="%s" > actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'Tag name filtering allows slashes in tag names' '
- git tag -m tag-with-slash X/1 &&
- git cat-file tag X/1 | sed -e s,X/1,X/2, > expect &&
- git filter-branch -f --tag-name-filter "echo X/2" &&
- git cat-file tag X/2 > actual &&
- test_cmp expect actual
-'
-test_expect_success 'setup --prune-empty comparisons' '
- git checkout --orphan master-no-a &&
- git rm -rf . &&
- unset test_tick &&
- test_tick &&
- GIT_COMMITTER_DATE="@0 +0000" GIT_AUTHOR_DATE="@0 +0000" &&
- test_commit --notick B B.t B Bx &&
- git checkout -b branch-no-a Bx &&
- test_commit D D.t D Dx &&
- mkdir dir &&
- test_commit dir/D dir/D.t dir/D dir/Dx &&
- test_commit E E.t E Ex &&
- git checkout master-no-a &&
- test_commit C C.t C Cx &&
- git checkout branch-no-a &&
- git merge Cx -m "Merge tag '\''C'\'' into branch" &&
- git tag Fx &&
- test_commit G G.t G Gx &&
- test_commit H H.t H Hx &&
- git checkout branch
-'
-
-test_expect_success 'Prune empty commits' '
- git rev-list HEAD > expect &&
- test_commit to_remove &&
- git filter-branch -f --index-filter "git update-index --remove to_remove.t" --prune-empty HEAD &&
- git rev-list HEAD > actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'prune empty collapsed merges' '
- test_config merge.ff false &&
- git rev-list HEAD >expect &&
- test_commit to_remove_2 &&
- git reset --hard HEAD^ &&
- test_merge non-ff to_remove_2 &&
- git filter-branch -f --index-filter "git update-index --remove to_remove_2.t" --prune-empty HEAD &&
- git rev-list HEAD >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'prune empty works even without index/tree filters' '
- git rev-list HEAD >expect &&
- git commit --allow-empty -m empty &&
- git filter-branch -f --prune-empty HEAD &&
- git rev-list HEAD >actual &&
- test_cmp expect actual
-'
-
-test_expect_success '--prune-empty is able to prune root commit' '
- git rev-list branch-no-a >expect &&
- git branch testing H &&
- git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t" testing &&
- git rev-list testing >actual &&
- git branch -D testing &&
- test_cmp expect actual
-'
-
-test_expect_success '--prune-empty is able to prune entire branch' '
- git branch prune-entire B &&
- git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire &&
- test_path_is_missing .git/refs/heads/prune-entire &&
- test_must_fail git reflog exists refs/heads/prune-entire
-'
-
-test_expect_success '--remap-to-ancestor with filename filters' '
- git checkout master &&
- git reset --hard A &&
- test_commit add-foo foo 1 &&
- git branch moved-foo &&
- test_commit add-bar bar a &&
- git branch invariant &&
- orig_invariant=$(git rev-parse invariant) &&
- git branch moved-bar &&
- test_commit change-foo foo 2 &&
- git filter-branch -f --remap-to-ancestor \
- moved-foo moved-bar A..master \
- -- -- foo &&
- test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&
- test $(git rev-parse moved-foo) = $(git rev-parse master^) &&
- test $orig_invariant = $(git rev-parse invariant)
-'
-
-test_expect_success 'automatic remapping to ancestor with filename filters' '
- git checkout master &&
- git reset --hard A &&
- test_commit add-foo2 foo 1 &&
- git branch moved-foo2 &&
- test_commit add-bar2 bar a &&
- git branch invariant2 &&
- orig_invariant=$(git rev-parse invariant2) &&
- git branch moved-bar2 &&
- test_commit change-foo2 foo 2 &&
- git filter-branch -f \
- moved-foo2 moved-bar2 A..master \
- -- -- foo &&
- test $(git rev-parse moved-foo2) = $(git rev-parse moved-bar2) &&
- test $(git rev-parse moved-foo2) = $(git rev-parse master^) &&
- test $orig_invariant = $(git rev-parse invariant2)
-'
-
-test_expect_success 'setup submodule' '
- rm -fr ?* .git &&
- git init &&
- test_commit file &&
- mkdir submod &&
- submodurl="$PWD/submod" &&
- ( cd submod &&
- git init &&
- test_commit file-in-submod ) &&
- git submodule add "$submodurl" &&
- git commit -m "added submodule" &&
- test_commit add-file &&
- ( cd submod && test_commit add-in-submodule ) &&
- git add submod &&
- git commit -m "changed submodule" &&
- git branch original HEAD
-'
-
-orig_head=$(git show-ref --hash --head HEAD)
-
-test_expect_success 'rewrite submodule with another content' '
- git filter-branch --tree-filter "test -d submod && {
- rm -rf submod &&
- git rm -rf --quiet submod &&
- mkdir submod &&
- : > submod/file
- } || :" HEAD &&
- test $orig_head != $(git show-ref --hash --head HEAD)
-'
-
-test_expect_success 'replace submodule revision' '
- git reset --hard original &&
- git filter-branch -f --tree-filter \
- "if git ls-files --error-unmatch -- submod > /dev/null 2>&1
- then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod
- fi" HEAD &&
- test $orig_head != $(git show-ref --hash --head HEAD)
-'
-
-test_expect_success 'filter commit message without trailing newline' '
- git reset --hard original &&
- commit=$(printf "no newline" | git commit-tree HEAD^{tree}) &&
- git update-ref refs/heads/no-newline $commit &&
- git filter-branch -f refs/heads/no-newline &&
- echo $commit >expect &&
- git rev-parse refs/heads/no-newline >actual &&
- test_cmp expect actual
-'
-
-test_expect_success 'tree-filter deals with object name vs pathname ambiguity' '
- test_when_finished "git reset --hard original" &&
- ambiguous=$(git rev-list -1 HEAD) &&
- git filter-branch --tree-filter "mv file.t $ambiguous" HEAD^.. &&
- git show HEAD:$ambiguous
-'
-
-test_expect_success 'rewrite repository including refs that point at non-commit object' '
- test_when_finished "git reset --hard original" &&
- tree=$(git rev-parse HEAD^{tree}) &&
- test_when_finished "git replace -d $tree" &&
- echo A >new &&
- git add new &&
- new_tree=$(git write-tree) &&
- git replace $tree $new_tree &&
- git tag -a -m "tag to a tree" treetag $new_tree &&
- git reset --hard HEAD &&
- git filter-branch -f -- --all >filter-output 2>&1 &&
- ! fgrep fatal filter-output
-'
-
-test_done
diff --git a/t/t7009-filter-branch-null-sha1.sh b/t/t7009-filter-branch-null-sha1.sh
deleted file mode 100755
index 9ba9f24ad2..0000000000
--- a/t/t7009-filter-branch-null-sha1.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-
-test_description='filter-branch removal of trees with null sha1'
-. ./test-lib.sh
-
-test_expect_success 'setup: base commits' '
- test_commit one &&
- test_commit two &&
- test_commit three
-'
-
-test_expect_success 'setup: a commit with a bogus null sha1 in the tree' '
- {
- git ls-tree HEAD &&
- printf "160000 commit $ZERO_OID\\tbroken\\n"
- } >broken-tree &&
- echo "add broken entry" >msg &&
-
- tree=$(git mktree <broken-tree) &&
- test_tick &&
- commit=$(git commit-tree $tree -p HEAD <msg) &&
- git update-ref HEAD "$commit"
-'
-
-# we have to make one more commit on top removing the broken
-# entry, since otherwise our index does not match HEAD (and filter-branch will
-# complain). We could make the index match HEAD, but doing so would involve
-# writing a null sha1 into the index.
-test_expect_success 'setup: bring HEAD and index in sync' '
- test_tick &&
- git commit -a -m "back to normal"
-'
-
-test_expect_success 'noop filter-branch complains' '
- test_must_fail git filter-branch \
- --force --prune-empty \
- --index-filter "true"
-'
-
-test_expect_success 'filter commands are still checked' '
- test_must_fail git filter-branch \
- --force --prune-empty \
- --index-filter "git rm --cached --ignore-unmatch three.t"
-'
-
-test_expect_success 'removing the broken entry works' '
- echo three >expect &&
- git filter-branch \
- --force --prune-empty \
- --index-filter "git rm --cached --ignore-unmatch broken" &&
- git log -1 --format=%s >actual &&
- test_cmp expect actual
-'
-
-test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 75512c3403..4e7f669c76 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -28,10 +28,10 @@ complete ()
#
# (2) A test makes sure that common subcommands are included in the
# completion for "git <TAB>", and a plumbing is excluded. "add",
-# "filter-branch" and "ls-files" are listed for this.
+# "rebase" and "ls-files" are listed for this.
-GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr filter-branch ls-files'
-GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout filter-branch'
+GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr rebase ls-files'
+GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
@@ -1392,12 +1392,12 @@ test_expect_success 'basic' '
# built-in
grep -q "^add \$" out &&
# script
- grep -q "^filter-branch \$" out &&
+ grep -q "^rebase \$" out &&
# plumbing
! grep -q "^ls-files \$" out &&
- run_completion "git f" &&
- ! grep -q -v "^f" out
+ run_completion "git r" &&
+ ! grep -q -v "^r" out
'
test_expect_success 'double dash "git" itself' '
--
2.23.0.3.gcc10030edf.dirty
next prev parent reply other threads:[~2019-08-28 0:22 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-22 18:26 RFC: Proposing git-filter-repo for inclusion in git.git Elijah Newren
2019-08-22 20:23 ` Junio C Hamano
2019-08-22 21:12 ` Elijah Newren
2019-08-22 21:34 ` Junio C Hamano
2019-08-26 23:52 ` [RFC PATCH 0/5] Remove git-filter-branch from git.git; host it elsewhere Elijah Newren
2019-08-26 23:52 ` [RFC PATCH 1/5] t6006: simplify and optimize empty message test Elijah Newren
2019-08-27 1:23 ` Derrick Stolee
2019-08-26 23:52 ` [RFC PATCH 2/5] t3427: accelerate this test by using fast-export and fast-import Elijah Newren
2019-08-27 1:25 ` Derrick Stolee
2019-08-26 23:52 ` [RFC PATCH 3/5] git-sh-i18n: work with external scripts Elijah Newren
2019-08-27 1:28 ` Derrick Stolee
2019-08-26 23:52 ` [RFC PATCH 4/5] Recommend git-filter-repo instead of git-filter-branch in documentation Elijah Newren
2019-08-27 1:32 ` Derrick Stolee
2019-08-27 6:23 ` Elijah Newren
2019-08-26 23:52 ` [RFC PATCH 5/5] Remove git-filter-branch, it is now external to git.git Elijah Newren
2019-08-27 1:39 ` [RFC PATCH 0/5] Remove git-filter-branch from git.git; host it elsewhere Derrick Stolee
2019-08-27 6:17 ` Elijah Newren
2019-08-27 7:03 ` Eric Wong
2019-08-27 8:43 ` Sergey Organov
2019-08-27 22:18 ` Elijah Newren
2019-08-28 8:52 ` Sergey Organov
2019-08-28 17:16 ` Elijah Newren
2019-08-28 19:03 ` Sergey Organov
2019-08-30 20:40 ` Johannes Schindelin
2019-08-30 23:22 ` Elijah Newren
2019-09-02 9:29 ` Johannes Schindelin
2019-09-03 17:37 ` Elijah Newren
2019-08-28 0:22 ` [PATCH v2 0/4] Warn about git-filter-branch usage and avoid it Elijah Newren
2019-08-28 0:22 ` [PATCH v2 1/4] t6006: simplify and optimize empty message test Elijah Newren
2019-08-28 0:22 ` [PATCH v2 2/4] t3427: accelerate this test by using fast-export and fast-import Elijah Newren
2019-08-28 6:00 ` Eric Sunshine
2019-08-28 0:22 ` [PATCH v2 3/4] Recommend git-filter-repo instead of git-filter-branch Elijah Newren
2019-08-28 6:17 ` Eric Sunshine
2019-08-28 21:48 ` Elijah Newren
2019-08-28 0:22 ` Elijah Newren [this message]
2019-08-29 0:06 ` [PATCH v3 0/4] Warn about git-filter-branch usage and avoid it Elijah Newren
2019-08-29 0:06 ` [PATCH v3 1/4] t6006: simplify and optimize empty message test Elijah Newren
2019-08-29 0:06 ` [PATCH v3 2/4] t3427: accelerate this test by using fast-export and fast-import Elijah Newren
2019-08-29 0:06 ` [PATCH v3 3/4] Recommend git-filter-repo instead of git-filter-branch Elijah Newren
2019-08-29 18:10 ` Eric Sunshine
2019-08-30 0:04 ` Elijah Newren
2019-08-29 0:06 ` [PATCH v3 4/4] t9902: use a non-deprecated command for testing Elijah Newren
2019-08-30 5:57 ` [PATCH v4 0/4] Warn about git-filter-branch usage and avoid it Elijah Newren
2019-08-30 5:57 ` [PATCH v4 1/4] t6006: simplify and optimize empty message test Elijah Newren
2019-09-02 14:47 ` Johannes Schindelin
2019-08-30 5:57 ` [PATCH v4 2/4] t3427: accelerate this test by using fast-export and fast-import Elijah Newren
2019-09-02 14:45 ` Johannes Schindelin
2019-08-30 5:57 ` [PATCH v4 3/4] Recommend git-filter-repo instead of git-filter-branch Elijah Newren
2019-08-30 5:57 ` [PATCH v4 4/4] t9902: use a non-deprecated command for testing Elijah Newren
2019-09-03 18:55 ` [PATCH v5 0/4] Warn about git-filter-branch usage and avoid it Elijah Newren
2019-09-03 18:55 ` [PATCH v5 1/4] t6006: simplify and optimize empty message test Elijah Newren
2019-09-03 21:08 ` Junio C Hamano
2019-09-03 21:58 ` Elijah Newren
2019-09-03 22:25 ` Junio C Hamano
2019-09-03 18:55 ` [PATCH v5 2/4] t3427: accelerate this test by using fast-export and fast-import Elijah Newren
2019-09-03 21:26 ` Junio C Hamano
2019-09-03 22:46 ` Junio C Hamano
2019-09-04 20:32 ` Elijah Newren
2019-09-03 18:55 ` [PATCH v5 3/4] Recommend git-filter-repo instead of git-filter-branch Elijah Newren
2019-09-03 21:40 ` Junio C Hamano
2019-09-04 20:30 ` Elijah Newren
2019-09-03 18:55 ` [PATCH v5 4/4] t9902: use a non-deprecated command for testing Elijah Newren
2019-09-04 22:32 ` [PATCH v6 0/3] Warn about git-filter-branch usage and avoid it Elijah Newren
2019-09-04 22:32 ` [PATCH v6 1/3] t6006: simplify, fix, and optimize empty message test Elijah Newren
2019-09-04 22:32 ` [PATCH v6 2/3] Recommend git-filter-repo instead of git-filter-branch Elijah Newren
2019-09-04 22:32 ` [PATCH v6 3/3] t9902: use a non-deprecated command for testing Elijah Newren
2019-08-23 3:00 ` RFC: Proposing git-filter-repo for inclusion in git.git Eric Wong
2019-08-23 18:06 ` Elijah Newren
2019-08-23 18:29 ` Elijah Newren
2019-08-28 11:09 ` Johannes Schindelin
2019-08-28 15:06 ` Junio C Hamano
2019-08-23 12:02 ` Derrick Stolee
2019-08-26 19:56 ` Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190828002210.8862-5-newren@gmail.com \
--to=newren@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=avarab@gmail.com \
--cc=e@80x24.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@gmail.com \
--cc=larsxschneider@gmail.com \
--cc=peff@peff.net \
--cc=stolee@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).