{"thread":{"id":"9093","subject":"[PATCH 2/2] filter-branch: introduce convenience function \"skip_commit\"","startedAt":"2007-07-18T15:54:04Z","lastAt":"2007-07-18T15:54:04Z","messageCount":1,"participants":["Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"47745","messageId":"Pine.LNX.4.64.0707181653460.14781@racer.site","threadId":"9093","inReplyTo":null,"subject":"[PATCH 2/2] filter-branch: introduce convenience function \"skip_commit\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-18T15:54:04Z","receivedAt":"2007-07-18T15:54:04Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWith this function, a commit filter can leave out unwanted commits\n(such as temporary commits).  It does _not_ undo the changeset\ncorresponding to that commit, but it _skips_ the revision.  IOW\nits childrens' tree objects remain the same.\n\nIf you like to commit early and often, but want to filter out all\nintermediate commits, marked by \"@@@\" in the commit message, you can\nnow do this with\n\n\tgit filter-branch --commit-filter '\n\t\tif git cat-file commit $GIT_COMMIT | grep '@@@' > /dev/null;\n\t\tthen\n\t\t\tskip_commit \"$@\";\n\t\telse\n\t\t\tgit commit-tree \"$@\";\n\t\tfi' newbranch\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/git-filter-branch.txt |   39 ++++++++++++++++++++++++----------\n git-filter-branch.sh                |   14 ++++++++++++\n t/t7003-filter-branch.sh            |    8 +------\n 3 files changed, 42 insertions(+), 19 deletions(-)\n\ndiff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt\nindex eaea82d..9dade65 100644\n--- a/Documentation/git-filter-branch.txt\n+++ b/Documentation/git-filter-branch.txt\n@@ -111,6 +111,11 @@ OPTIONS\n As a special extension, the commit filter may emit multiple\n commit ids; in that case, ancestors of the original commit will\n have all of them as parents.\n++\n+You can use the 'map' convenience function in this filter, and other\n+convenience functions, too.  For example, calling 'skip_commit \"$@\"'\n+will leave out the current commit (but not its changes! If you want\n+that, use gitlink:git-rebase[1] instead).\n \n --tag-name-filter <command>::\n \tThis is the filter for rewriting tag names. When passed,\n@@ -199,34 +204,44 @@ To remove commits authored by \"Darl McBribe\" from the history:\n git filter-branch --commit-filter '\n \tif [ \"$GIT_AUTHOR_NAME\" = \"Darl McBribe\" ];\n \tthen\n-\t\tshift;\n-\t\twhile [ -n \"$1\" ];\n-\t\tdo\n-\t\t\tshift;\n-\t\t\techo \"$1\";\n-\t\t\tshift;\n-\t\tdone;\n+\t\tskip_commit \"$@\";\n \telse\n \t\tgit commit-tree \"$@\";\n \tfi' newbranch\n ------------------------------------------------------------------------------\n \n+Note that the changes introduced by the commits, and not reverted by\n+subsequent commits, will still be in the rewritten branch. If you want\n+to throw out _changes_ together with the commits, you should use the\n+interactive mode of gitlink:git-rebase[1].\n+\n+The function 'skip_commits' is defined as follows:\n+\n+--------------------------\n+skip_commit()\n+{\n+\tshift;\n+\twhile [ -n \"$1\" ];\n+\tdo\n+\t\tshift;\n+\t\tmap \"$1\";\n+\t\tshift;\n+\tdone;\n+}\n+--------------------------\n+\n The shift magic first throws away the tree id and then the -p\n parameters.  Note that this handles merges properly! In case Darl\n committed a merge between P1 and P2, it will be propagated properly\n and all children of the merge will become merge commits with P1,P2\n as their parents instead of the merge commit.\n \n+\n To restrict rewriting to only part of the history, specify a revision\n range in addition to the new branch name.  The new branch name will\n point to the top-most revision that a 'git rev-list' of this range\n will print.\n \n-Note that the changes introduced by the commits, and not reverted by\n-subsequent commits, will still be in the rewritten branch. If you want\n-to throw out _changes_ together with the commits, you should use the\n-interactive mode of gitlink:git-rebase[1].\n-\n Consider this history:\n \n ------------------\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex b574612..91f3677 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -23,6 +23,20 @@ map()\n \tfi\n }\n \n+# if you run 'skip_commit \"$@\"' in a commit filter, it will print\n+# the (mapped) parents, effectively skipping the commit.\n+\n+skip_commit()\n+{\n+\tshift;\n+\twhile [ -n \"$1\" ];\n+\tdo\n+\t\tshift;\n+\t\tmap \"$1\";\n+\t\tshift;\n+\tdone;\n+}\n+\n # override die(): this version puts in an extra line break, so that\n # the progress is still visible\n \ndiff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh\nindex 4ddd656..22bb14a 100755\n--- a/t/t7003-filter-branch.sh\n+++ b/t/t7003-filter-branch.sh\n@@ -132,13 +132,7 @@ test_expect_success \"remove a certain author's commits\" '\n \tgit-filter-branch --commit-filter \"\\\n \t\tif [ \\\"\\$GIT_AUTHOR_NAME\\\" = \\\"B V Uips\\\" ];\\\n \t\tthen\\\n-\t\t\tshift;\\\n-\t\t\twhile [ -n \\\"\\$1\\\" ];\\\n-\t\t\tdo\\\n-\t\t\t\tshift;\\\n-\t\t\t\techo \\\"\\$1\\\";\\\n-\t\t\t\tshift;\\\n-\t\t\tdone;\\\n+\t\t\tskip_commit \\\"\\$@\\\";\n \t\telse\\\n \t\t\tgit commit-tree \\\"\\$@\\\";\\\n \t\tfi\" removed-author &&\n-- \n1.5.3.rc1.16.g9d6f-dirty\n"}]}