我想创建一个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之间)尚未被提出。如果我错了,抱歉浪费你的时间。感谢那些试图回答这个问题的人!
答案 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_NAME
,GIT_COMMITTER_EMAIL
和GIT_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 \"\$@\""