Running filter-branch with --prune-empty and --commit-filter reports:
"Cannot set --prune-empty and --filter-commit at the same time".
Change it to use the correct option name: --commit-filter
Signed-off-by: Jacob Helwig <jacob.helwig@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When git filter-branch is used to replace a submodule with another
content, it always fails on the first commit.
Consider a repository with submod directory containing a submodule. The
following command to remove the submodule and replace it with a file fails:
git filter-branch --tree-filter 'rm -rf submod &&
git rm -q submod &&
mkdir submod &&
touch submod/file'
with an error:
error: submod: is a directory - add files inside instead
The reason is that git diff-index, which generates the first part of the
list of files updated by the tree filter, emits also the removed submodule
even if it was replaced by a real directory.
Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Using a dollar sign in double quotes isn't portable. Escape them with
a backslash or replace the double quotes with single quotes.
Signed-off-by: Stephen Boyd <bebarino@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The intent of this particular call to 'git read-tree' was to fill an
index. But in fact, it only allocated an empty index. Later in the
program, the index is filled anyway by calling read-tree with specific
commits, and considering that elsewhere the index is even removed (i.e.,
it is not relied upon that the index file exists), this first call of
read-tree is completely redundant.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
If the user has exported the GREP_OPTIONS environment variable, the output
from "grep" and "egrep" in scripted Porcelains may be different from what
they expect. For example, we may want to count number of matching lines,
by "grep" piped to "wc -l", and GREP_OPTIONS=-C3 will break such use.
The approach taken by this change to address this issue is to protect only
our own use of grep/egrep. Because we do not unset it at the beginning of
our scripts, hook scripts run from the scripted Porcelains are exposed to
the same insanity this environment variable causes when grep/egrep is used
to implement logic (e.g. "grep | wc -l"), and it is entirely up to the
hook scripts to protect themselves.
On the other hand, applypatch-msg hook may want to show offending words in
the proposed commit log message using grep to the end user, and the user
might want to set GREP_OPTIONS=--color to paint the match more visibly.
The approach to protect only our own use without unsetting the environment
variable globally will allow this use case.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Since a0e4639 (filter-branch: fix ref rewriting with
--subdirectory-filter, 2008-08-12) git-filter-branch has done
nearest-ancestor rewriting when using a --subdirectory-filter.
However, that rewriting strategy is also a useful building block in
other tasks. For example, if you want to split out a subset of files
from your history, you would typically call
git filter-branch -- <refs> -- <files>
But this fails for all refs that do not point directly to a commit
that affects <files>, because their referenced commit will not be
rewritten and the ref remains untouched.
The code was already there for the --subdirectory-filter case, so just
introduce an option that enables it independently.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Handling $filter_subdir in the usual way requires a separate case at
every use, because the variable is empty when unused.
Furthermore, --subdirectory-filter supplies its own '--', and if the user
provided one himself, such as in
git filter-branch --subdirectory-filter subdir -- --all -- subdir/file
an extra '--' was used as path filter in the call to git-rev-list that
determines the commits that shall be rewritten.
To keep the argument handling sane, we filter $@ to contain only the
non-revision arguments, and store all revisions in $ref_args. The
$ref_args are easy to handle since only the SHA1s are needed; the
actual branch names have already been stored in $tempdir/heads at this
point.
An extra separating -- is only required if the user did not provide
any non-revision arguments, as the latter disambiguate the
$filter_subdir following after them (or fail earlier because they are
ambiguous themselves).
Thanks to Johannes Sixt for suggesting this solution.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
It used to be a single, huge line, badly wrapped by xterm.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
A minor fix that eliminates usage of "2>/dev/null" when --quiet or
-q has already been implemented.
Signed-off-by: Dan Loewenherz <daniel.loewenherz@yale.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Avoid using simple variable names like 'i', since user commands are eval'ed
and may clash with and overwrite our values.
Signed-off-by: Elijah Newren <newren@gmail.com>
Acked-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Tell the user that a backup (original) already exists, and how to solve
this problem (with -f option)
Signed-off-by: John Tapsell <johnflux@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The improved error handling catches a bug in filter-branch when using
-d pointing to a path outside any git repository:
$ git filter-branch -d /tmp/foo master
fatal: Not a git repository (or any of the parent directories): .git
This error message comes from git for-each-ref in line 224. GIT_DIR is
set correctly by git-sh-setup (to the foo.git repository), but not
exported (yet).
Signed-off-by: Lars Noschinski <lars@public.noschinski.de>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
9273b56 (filter-branch: Fix fatal error on bare repositories, 2009-02-03)
fixed a missing check of return status from an underlying command in
git-filter-branch, but there still are places that do not check errors.
For example, the command does not pay attention to the exit status of the
command given by --commit-filter. It should abort in such a case.
This attempts to fix all the remaining places that fails to checks errors.
In two places, I've had to break apart pipelines in order to check the
error code for the first stage of the pipeline, as discussed here:
http://kerneltrap.org/mailarchive/git/2009/1/28/4835614
Feedback on this patch was provided by Johannes Sixt, Johannes Schindelin
and Junio C Hamano. Thomas Rast helped with pipeline error handling.
Signed-off-by: Eric Kidd <git@randomhacks.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
At the end of filter-branch in a non-bare repository, the work tree is
updated with "read-tree -m -u HEAD", to carry the change forward in case
the current branch was rewritten. In order to avoid losing any local
change during this step, filter-branch refuses to work when there are
local changes in the work tree.
This "read-tree -m -u HEAD" operation does not affect what commit is
checked out in a submodule (iow, it does not touch .git/HEAD in a
submodule checkout), and checking if there is any local change to the
submodule is not useful.
Staged submodules _are_ considered to be 'dirty', however, as the
"read-tree -m -u HEAD" could result in loss of staged information
otherwise.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When git filter-branch is run on a bare repository, it prints out a fatal
error message:
$ git filter-branch branch
Rewrite 476c4839280c219c2317376b661d9d95c1727fc3 (9/9)
WARNING: Ref 'refs/heads/branch' is unchanged
fatal: This operation must be run in a work tree
Note that this fatal error message doesn't prevent git filter-branch from
exiting successfully. (Why doesn't git filter-branch actually exit with an
error when a shell command fails? I'm not sure why it was designed this
way.)
This error message is caused by the following section of code at the end of
git-filter-branch.sh:
if [ "$(is_bare_repository)" = false ]; then
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
test -z "$ORIG_GIT_DIR" || {
GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
}
... elided ...
git read-tree -u -m HEAD
fi
The problem is the call to $(is_bare_repository), which is made before
GIT_DIR and GIT_WORK_TREE are restored. This call always returns "false",
even when we're running in a bare repository. But this means that we will
attempt to call 'git read-tree' even in a bare repository, which will fail
and print an error.
This patch modifies git-filter-branch.sh to restore the original
environment variables before trying to call is_bare_repository.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git_commit_non_empty_tree is added to the functions that can be run from
commit filters. Its effect is to commit only commits actually touching the
tree and that are not merge points either.
The option --prune-empty is added. It defaults the commit-filter to
'git_commit_non_empty_tree "$@"', and can be used with any other
combination of filters, except --commit-hook that must used
'git_commit_non_empty_tree "$@"' where one puts 'git commit-tree "$@"'
usually to achieve the same result.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The tag rewriting code used a 'sed' expression to substitute the new tag
name into the corresponding field of the annotated tag object. But this is
problematic if the tag name contains special characters. In particular,
if the tag name contained a slash, then the 'sed' expression had a syntax
error. We now protect against this by using 'printf' to assemble the
tag header.
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Use rev-list --simplify-merges everywhere. This changes the behaviour
of --subdirectory-filter in cases such as
O -- A -\
\ \
\- B -- M
where A and B bring the same changes to the subdirectory: It now keeps
both sides of the merge. Previously, the history would have been
simplified to 'O -- A'. Merges of unrelated side histories that never
touch the subdirectory are still removed.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The previous ancestor discovery code failed on any refs that are
(pre-rewrite) ancestors of commits marked for rewriting. This means
that in a situation
A -- B(topic) -- C(master)
where B is dropped by --subdirectory-filter pruning, the 'topic' was
not moved up to A as intended, but left unrewritten because we asked
about 'git rev-list ^master topic', which does not return anything.
Instead, we use the straightforward
git rev-list -1 $ref -- $filter_subdir
to find the right ancestor. To justify this, note that the nearest
ancestor is unique: We use the output of
git rev-list --parents -- $filter_subdir
to rewrite commits in the first pass, before any ref rewriting. If B
is a non-merge commit, the only candidate is its parent. If it is a
merge, there are two cases:
- All sides of the merge bring the same subdirectory contents. Then
rev-list already pruned away the merge in favour for just one of its
parents, so there is only one candidate.
- Some merge sides, or the merge outcome, differ. Then the merge is
not pruned and can be rewritten directly.
So it is always safe to use rev-list -1.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Previously, git-filter-branch failed if it attempted to update an
annotated tag. Now we ignore this condition if --tag-name-filter is
given, so that we can later rewrite the tag. If no such option was
provided, we warn the user that he might want to run with
"--tag-name-filter cat" to achieve the intended effect.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Commit 46eb449c restricted git-filter-branch to non-bare repositories
unnecessarily; git-filter-branch can work on bare repositories just
fine.
Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This reverts commit cfabd6eee1. I had
implemented it without understanding what --full-history does. Consider
this history:
C--M--N
/ / /
A--B /
\ /
D-/
where B and C modify a path, X, in the same way so that the result is
identical, and D does not modify it at all. With the path limiter X and
without --full-history this is simplified to
A--B
i.e. only one of the paths via B or C is chosen. I had assumed that
--full-history would keep both paths like this
C--M
/ /
A--B
removing the path via D; but in fact it keeps the entire history.
Currently, git does not have the capability to simplify to this
intermediary case. However, the other extreme to keep the entire history
is not wanted either in usual cases. I think we can expect that histories
like the above are rare, and in the usual cases we want a simplified
history. So let's remove --full-history again.
(Concerning t7003, subsequent tests depend on what the test case sets up,
so we can't just back out the entire test case.)
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
filter-branch tries to restore "old" copies of some
environment variables by using the construct:
unset var
test -z "$old_var" || var="$old_var" && export var
This is just wrong. AND-list and OR-list operators && and || have equal
precedence and they bind left to right. The second term, var="$old"
assignment always succeeds, so we always end up exporting var.
On bash and dash, exporting an unset variable has no effect. However, on
some shells (such as FreeBSD's /bin/sh), the shell exports the empty
value.
This manifested itself in this case as git-filter-branch setting
GIT_INDEX_FILE to the empty string, which in turn caused its call to
git-read-tree to fail, leaving the working tree pointing at the original
HEAD instead of the rewritten one.
To fix this, we change the short-circuit logic to better match the intent:
test -z "$old_var" || {
var="$old_var" && export var
}
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Commit d89c1df (filter-branch: don't use xargs -0, 2008-03-12) replaced a
'ls-files | xargs rm' pipeline by 'git clean'. 'git clean' however does
not recurse and remove directories by default.
Now, consider a tree-filter that renames a directory.
1. For the first commit everything works as expected
2. Then filter-branch checks out the files for the next commit. This
leaves the new directory behind because there is no real "branch
switching" involved that would notice that the directory can be
removed.
3. Then filter-branch invokes 'git clean' to remove exactly those
left-overs. But here it does not remove the directory.
4. The next tree-filter does not work as expected because there already
exists a directory with the new name.
Just add -d to 'git clean', so that empty directories are removed.
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Add support for creating a new tag object and retaining the tag message,
author, and date when rewriting tags. The gpg signature, if one exists,
will be stripped.
This adds nearly proper tag name filtering to filter-branch. Proper tag
name filtering would include the ability to change the tagger, tag date,
tag message, and _not_ strip a gpg signature if the tag did not change.
Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
On some systems, 'sh' isn't very friendly. In particular,
t7003 fails on Solaris because it doesn't understand $().
Instead, use the specified SHELL_PATH to run shell code.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Some versions of xargs don't understand "-0"; fortunately in
this case we can get the same effect by using "git clean".
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Specifying character ranges in tr differs between System V
and POSIX. In System V, brackets are required (e.g.,
'[A-Z]'), whereas in POSIX they are not.
We can mostly get around this by just using the bracket form
for both sets, as in:
tr '[A-Z] '[a-z]'
in which case POSIX interpets this as "'[' becomes '['",
which is OK.
However, this doesn't work with multiple sequences, like:
# rot13
tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]'
where the POSIX version does not behave the same as the
System V version. In this case, we must simply enumerate the
sequence.
This patch fixes problematic uses of tr in git scripts and
test scripts in one of three ways:
- if a single sequence, make sure it uses brackets
- if multiple sequences, enumerate
- if extra brackets (e.g., tr '[A]' 'a'), eliminate
brackets
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The subdirectory filter had a bug to notice that the commit in question
did not have anything in the path-limited part of the tree. $commit:$path
does not name an empty tree when $path does not appear in $commit.
This should fix it. The additional test in t7003 is originally from Kevin
Ballard but with fixups.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The command used a very old fashioned construct to extract
filenames out of diff-index and ended up corrupting the output.
We can simply use --name-only and pipe into --stdin mode of
update-index. It's been like that for the past 2 years or so
since a94d994 (update-index: work with c-quoted name).
Signed-off-by: Junio C Hamano <gitster@pobox.com>
filter-branch previously took the first non-option argument as the name for
a new branch. Since dfd05e38, it now takes a revision or a revision range
and modifies the current branch. Update to operate on HEAD by default to
conform with standard git interface practice.
Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
One of the first things filter-branch does is to create a temporary
directory. This directory is eventually removed by the script during
normal operation, but is not removed if the script encounters an error.
Set a trap to remove it when the script terminates for any reason.
Signed-off-by: Brandon Casey <casey@nrlssc.navy.mil>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
'git-filter-branch branch' could fail producing the error:
"Which ref do you want to rewrite?" if existed another branch
or tag, which name was 'branch-something' or 'something/branch'.
[jc: original report and fix were done between Dmitry Potapov
and Dscho; I rewrote it using "rev-parse --symbolic-full-name"]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
I hesitate to suggest this, since GNU tr has accepted \n for 15 years,
but there are supposedly a few crufty vendor-supplied versions of tr still
in use. Also, all of the other uses of tr-with-newline in git use \012.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
There was an attempt to list the refs that were rewritten by filtering
the output of 'git show-ref' for 'refs/original'. But it got the
grep argument wrong, which did not account for the SHA1 that is listed
before the ref.
Moreover, right before this summary is the loop that actually does the
rewriting, and the rewritten refs are listed there anyway. So this extra
summary is plainly too verbose.
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Some versions of 'tr' only accept octal codes if entered with three digits,
and therefor misinterpret the '\0' in the test suite.
Some versions of 'tr' reject the (needless) use of character classes.
Signed-off-by: H.Merijn Brand <h.m.brand@xs4all.nl>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
It might be POSIX, but there are shells that do not like the
expression 'export VAR=VAL'. To be on the safe side, rewrite them
into 'VAR=VAL' and 'export VAR'.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
When you have a file called HEAD in your work tree, many commands that
our scripts feed "HEAD" to would complain about the rev vs path
ambiguity. A solution is to form command line more carefully by
appending -- to them, which makes it clear that we mean HEAD rev not
HEAD file.
This patch would apply to maint.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
The helper functions 'map' and 'skip_commit' were provided to commit
filters by sourcing filter-branch itself. This was done with a certain
environment variable set to indicate that only the functions should be
defined, and the script should return then.
This was really hacky, and it did not work all that well, since the
full path to git-filter-branch was not known at all times.
Avoid that by putting the functions into a variable, and eval'ing
that variable. The commit filter gets these functions by prepending
the variable to the specified commands.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
--text follows this line--
These commands currently lack OPTIONS_SPEC; allow people to
easily list with "git grep 'OPTIONS_SPEC=$'" what they can help
improving.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Earlier, "git filter-branch --<options> HEAD" would not update the
working tree after rewriting the branch. This commit fixes it.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
A lot of shell scripts contained stuff starting with
while case "$#" in 0) break ;; esac
and similar. I consider breaking out of the condition instead of the
body od the loop ugly, and the implied "true" value of the
non-matching case is not really obvious to humans at first glance. It
happens not to be obvious to some BSD shells, either, but that's
because they are not POSIX-compliant. In most cases, this has been
replaced by a straight condition using "test". "case" has the
advantage of being faster than "test" on vintage shells where "test"
is not a builtin. Since none of them is likely to run the git
scripts, anyway, the added readability should be worth the change.
A few loops have had their termination condition expressed
differently.
Signed-off-by: David Kastrup <dak@gnu.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
With this function, a commit filter can leave out unwanted commits
(such as temporary commits). It does _not_ undo the changeset
corresponding to that commit, but it _skips_ the revision. IOW
no tree object is changed by this.
If you like to commit early and often, but want to filter out all
intermediate commits, marked by "@@@" in the commit message, you can
now do this with
git filter-branch --commit-filter '
if git cat-file commit $GIT_COMMIT | grep '@@@' > /dev/null;
then
skip_commit "$@";
else
git commit-tree "$@";
fi' newbranch
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Move the convenience functions to the top of git-filter-branch.sh, and
return from the script when the environment variable SOURCE_FUNCTIONS is
set.
By sourcing git-filter-branch with that variable set automatically, all
commit filters may access the convenience functions like "map".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Later in a loop any existing ref whose path begins with it is
removed. It would be a disaster if you allowed it to say refs/head
for example.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Remove "DESTBRANCH" from usage, as it rewrites the branches given.
- Remove an = from an example usage, as the script doesn't understand
it.
Signed-off-by: Brian Gernhardt <benji@silverinsanity.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>