简体   繁体   English

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

[英]git edit authors name in commit range, script

I would like to create a git script which replaces author "A" with author "B" in a specified commit range (abcd..dcba). 我想创建一个git脚本,在指定的提交范围(abcd..dcba)中用作者“B”替换作者“A”。 How can I do that? 我怎样才能做到这一点? Here is what I have so far: 这是我到目前为止:

#!/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 "$@"'

problem is that git says 问题是git说

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

Is the git rev-list --boundary command even legal in an if statement? git rev-list --boundary命令在if语句中是否合法? if i remove the if [git rev-list ... ] statement it'll work. 如果我删除if [git rev-list ...]语句,它将起作用。

Ideal would be if I can add input variables. 理想的是,如果我可以添加输入变量。 So the command would look like 所以命令看起来像

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

Edit: Some thinks that this question has already been asked. 编辑:有人认为这个问题已经被提出。 for those please read the problem above again and compare it wit the previously asked questions. 对于那些人,请再次阅读上面的问题,并将其与以前的问题进行比较。 AFAIK THIS question (test if commits are between commit A and commit B) has not been asked yet. AFAIK这个问题(测试提交是否在提交A和提交B之间)尚未提出。 If i'm wrong, sorry for wasting your time. 如果我错了,很抱歉浪费您的时间。 Thanks to those who have tried to answer that question! 感谢那些试图回答这个问题的人!

If you want to use parameters for the script, simply do 如果要为脚本使用参数,只需执行

#!/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 \"\$@\""

However, note that you will probably want to edit GIT_COMMITTER_NAME , GIT_COMMITTER_EMAIL and GIT_AUTHOR_EMAIL as well. 但请注意,您可能还想编辑GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILGIT_AUTHOR_EMAIL See this answer . 看到这个答案

You can substitute variables from your shell script into the script that you pass in to git filter-branch . 您可以将shell脚本中的变量替换为传递给git filter-branch的脚本。 You just need to be careful to get the quoting right. 你只需要小心得到正确的引用。 Since you're in single quotes, you can't substitute the variable directly, but you can end the single quotes and open a double quoted string for the substitution, then close the double quoted string and open the single quoted string back up again; 由于你是单引号,你不能直接替换变量,但你可以结束单引号并为替换打开双引号字符串,然后关闭双引号字符串并再次打开单引号字符串; the strings will be appended after expansion. 字符串将在扩展后追加。 And within the single quoted string, you should include quotes that will surround the expanded string from the variable, in case it contains spaces or other characters. 在单引号字符串中,如果它包含空格或其他字符,则应包含将从变量中包围扩展字符串的引号。

Rather than trying to limit the revisions within the filter script, it's better to just pass the revisions in to git filter-branch so that it will only ever do anything to those commits. 与其尝试在过滤器脚本中限制修订版,不如将修订版传递到git filter-branch这样它只会对那些提交做任何事情。 git filter-branch takes the same arguments as git rev-list at the end of the command (though you have to delimit them with a -- in order for it to interpret --boundary as an rev-list argument). git filter-branch在命令末尾使用与git rev-list相同的参数(尽管你必须用--分隔它们--以便它将--boundary解释为rev-list参数)。

#!/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"

edit : Missed the problem with git rev-list when first answering. 编辑 :第一次回答时,用git rev-list错过了问题。

Others have addressed parameter quoting. 其他人已经解决了参数引用。 The big remaining problem is the test: 剩下的最大问题是测试:

if [ git-rev-list ... ]

The commit filter is just a shell script fragment, so this tells the shell to run the command: 提交过滤器只是一个shell脚本片段,因此这告诉shell运行命令:

[ git-rev-list ... ]

and test whether the exit status of that command is zero (true) or not (false). 并测试该命令的退出状态是零(true)还是不(false)。 The [ command, also known as test , does not have any git built-ins. [ command,也称为test ,没有任何git内置函数。

What you seem to want is to tell whether the original commit being filtered is a member of the range A .. B inclusive. 您似乎想要的是判断被过滤的原始提交是否是A .. B范围内的成员。 Let's first note this, from the filter-branch documentation: 让我们首先从过滤器分支文档中注意到这一点:

The filters are applied in the order as listed below. 过滤器的应用顺序如下。 The <command> argument is always evaluated in the shell context using the eval command (with the notable exception of the commit filter, for technical reasons). 始终使用eval命令在shell上下文中评估<command>参数(出于技术原因,提交过滤器有明显的例外)。 Prior to that, the $GIT_COMMIT environment variable will be set to contain the id of the commit being rewritten. 在此之前, $GIT_COMMIT环境变量将被设置为包含要重写的提交的id。

Thus, you could write something like this: 因此,你可以这样写:

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

The first merge-base tests whether $GIT_COMMIT is an ancestor of the higher rev (is equal to $B or comes "before" it topologically). 第一个merge-base测试$GIT_COMMIT是否是更高转速的祖先(等于$B或者在拓扑之前“来”)。 The second excludes commits that come before the lower rev ( $A ), using the hat-suffix to avoid excluding $A itself. 第二个不包括在较低转速( $A )之前的提交,使用帽子后缀来避免排除$A本身。

Here's a variant of Brian Campbell's script using this technique (well, I also changed the quote expansion technique too). 这是Brian Campbell使用此技术的脚本的变体(嗯,我也更改了引号扩展技术)。

#! /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 \"\$@\""

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM