git在提交范围,脚本中编辑作者名称

时间:2013-10-07 13:40:28

标签: git bash shell

我想创建一个git脚本,在指定的提交范围(abcd..dcba)中用作者“B”替换作者“A”。我怎样才能做到这一点? 以下是我到目前为止的情况:

#!/bin/sh
#
# git-myCommand
#
#
git filter-branch --commit-filter '
    if  [ git rev-list --boundary 02e60c8..dc4c65f ]; then
        if [ "$GIT_AUTHOR_NAME" = "A" ];then
            GIT_AUTHOR_NAME="B";
        fi;
    fi;
git commit-tree "$@"'

问题是git说

Rewrite $SHA1-Number git commit-tree: line 48: [: too many arguments

git rev-list --boundary命令在if语句中是否合法? 如果我删除if [git rev-list ...]语句,它将起作用。

如果我可以添加输入变量,那将是理想的选择。 所以命令看起来像

git myCommand $AuthorExpression $AuthorReplace $CommitA..$CommitB

编辑:有人认为这个问题已被提出。对于那些请再次阅读上面的问题,并与之前提出的问题进行比较。 AFAIK这个问题(测试提交是否在提交A和提交B之间)尚未被提出。如果我错了,抱歉浪费你的时间。感谢那些试图回答这个问题的人!

3 个答案:

答案 0 :(得分:3)

如果您想使用脚本参数,只需执行

#!/bin/sh
#
# git-myCommand
#
#
AuthorExpression=$1
AuthorReplace=$2
CommitA=$3
CommitB=$4
git filter-branch --commit-filter "
    if git rev-list --boundary '$CommitA'..'$CommitB'; then
        if [ \"\$GIT_AUTHOR_NAME\" = '$AuthorExpression' ];then
            GIT_AUTHOR_NAME='$AuthorReplace';
        fi;
    fi;
git commit-tree \"\$@\""

但请注意,您可能还想修改GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILGIT_AUTHOR_EMAIL。请参阅this answer

答案 1 :(得分:2)

您可以将shell脚本中的变量替换为传递给git filter-branch的脚本。你只需要小心得到正确的引用。由于你是单引号,你不能直接替换变量,但你可以结束单引号并为替换打开双引号字符串,然后关闭双引号字符串并再次打开单引号字符串;扩展后将追加字符串。在单引号字符串中,如果它包含空格或其他字符,则应该包含将从变量中包围扩展字符串的引号。

不要试图限制过滤器脚本中的修订,最好只将修订版传递给git filter-branch,这样它只会对这些提交做任何事情。 git filter-branch在命令末尾使用与git rev-list相同的参数(尽管您必须使用--对其进行分隔,以便将--boundary解释为{rev-list 1}}参数)。

#!/bin/sh
#
# git-myCommand
#
#
AuthorExpression=$1
AuthorReplace=$2
CommitA=$3
CommitB=$4
git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_NAME" = "'"$AuthorExpression"'" ];then
        GIT_AUTHOR_NAME="'"$AuthorReplace"'";
    fi;
git commit-tree "$@"' -- --boundary "$CommitA".."$CommitB"

修改:第一次回答时错过了git rev-list的问题。

答案 2 :(得分:2)

其他人已经解决了参数引用问题。剩下的最大问题是测试:

if [ git-rev-list ... ]

提交过滤器只是一个shell脚本片段,因此它告诉shell运行命令:

[ git-rev-list ... ]

并测试该命令的退出状态是否为零(true)或不是(false)。 [命令(也称为test)没有任何git内置插件。

您似乎想要判断被过滤的原始提交是否属于 A .. B 范围内的成员。让我们首先从过滤器分支文档中注意到这一点:

  

过滤器按照下面列出的顺序应用。 < command>          始终使用eval在shell上下文中计算参数          命令(除了提交过滤器之外,对于技术          原因)。在此之前,$GIT_COMMIT环境变量将是          设置为包含要重写的提交的ID。

因此,你可以这样写:

A=$(git rev-parse $3) || exit 1
B=$(git rev-parse $4) || exit 1
git filter-branch --commit-filter "
    if git merge-base --is-ancestor \$GIT_COMMIT $B &&
       ! git merge-base --is-ancestor \$GIT_COMMIT $A^; then

第一个merge-base测试$GIT_COMMIT是否是较高转速的祖先(等于$B或者来自“拓扑之前”)。第二个排除了较低转速($A)之前的提交,使用后缀为后缀以避免排除$A本身。

这是使用这种技术的Brian Campbell's script的变体(好吧,我也改变了引用扩展技术)。

#! /bin/sh
case $# in
4) ;;
*) echo "usage: $0 oldauthor newauthor firstrev lastrev" >&2; exit 1;;
esac

AuthorExpression=$1
AuthorReplace=$2
A=$(git rev-parse --verify $3^{commit}) || exit 1
B=$(git rev-parse --verify $4^{commit}) || exit 1

git filter-branch --commit-filter "
    if git merge-base --is-ancestor \$GIT_COMMIT $B &&
       ! git merge-base --is-ancestor \$GIT_COMMIT $A^; then
       if [ \"\$GIT_AUTHOR_NAME\" = '$AuthorExpression' ]; then
       GIT_AUTHOR_NAME='$AuthorReplace'
       fi
    fi
git commit-tree \"\$@\""