Skip to content

Commit

Permalink
filter-branch: introduce convenience function "skip_commit"
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dscho authored and gitster committed Sep 1, 2007
1 parent 7e0f170 commit f95eef1
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
34 changes: 27 additions & 7 deletions Documentation/git-filter-branch.txt
Expand Up @@ -112,6 +112,11 @@ OPTIONS
As a special extension, the commit filter may emit multiple
commit ids; in that case, ancestors 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 gitlink:git-rebase[1] instead).

--tag-name-filter <command>::
This is the filter for rewriting tag names. When passed,
Expand Down Expand Up @@ -209,24 +214,39 @@ To remove commits authored by "Darl McBribe" from the history:
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
then
shift;
while [ -n "$1" ];
do
shift;
echo "$1";
shift;
done;
skip_commit "$@";
else
git commit-tree "$@";
fi' HEAD
------------------------------------------------------------------------------

Note that the changes introduced by the commits, and 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 gitlink:git-rebase[1].

The function 'skip_commits' 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.


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
Expand Down
14 changes: 14 additions & 0 deletions git-filter-branch.sh
Expand Up @@ -23,6 +23,20 @@ map()
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;
}

# override die(): this version puts in an extra line break, so that
# the progress is still visible

Expand Down
8 changes: 1 addition & 7 deletions t/t7003-filter-branch.sh
Expand Up @@ -138,13 +138,7 @@ test_expect_success "remove a certain author's commits" '
git-filter-branch -f --commit-filter "\
if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\
then\
shift;\
while [ -n \"\$1\" ];\
do\
shift;\
echo \"\$1\";\
shift;\
done;\
skip_commit \"\$@\";
else\
git commit-tree \"\$@\";\
fi" removed-author &&
Expand Down

0 comments on commit f95eef1

Please sign in to comment.