假设我想重命名git存储库中包含的源代码中的方法。我可以手动执行此操作,但方法名称可能位于多个位置(例如,单元测试,文档,实际方法)。要检查方法的使用位置,我使用'git grep'。我得到'git grep'只显示我想要更改的行,然后我没有自动更改这些行的工作流程。
我正在寻找一种自动化方式(希望使用git工具)来完成最后一步。我希望有某种'git sed'或等同物,但我找不到任何东西。
我认为的界面会很好:git sed's / old-method-name / new-method-name / g'
答案 0 :(得分:48)
您可以将git ls-files
与xargs
和sed
结合使用:
git ls-files -z | xargs -0 sed -i -e 's/old-method-name/new-method-name/g'
答案 1 :(得分:18)
感谢Noufal和Greg的帖子。我结合他们的解决方案,发现一个使用git grep(比我的repo更健壮的git ls文件,因为它似乎只列出了其中包含实际src代码的文件 - 例如,不是子模块文件夹),并且还有仅在一个地方使用旧方法名称和新方法名称:
在[alias]
文件的~/.gitconfig
块中:
sed = ! git grep -z --full-name -l '.' | xargs -0 sed -i -e
使用:
git sed 's/old-method-name/new-method-name/ig'
答案 2 :(得分:11)
你可以做一个
for i in $(git grep --full-name -l old_method_name)
do
perl -p -i -e 's/old_method_name/new_method_name/g' $i
done
将其粘贴到某个文件中,然后在配置中将其别名为git sed
。
更新:以下tchrist的评论是一个更好的解决方案,因为它可以防止perl重复产生。
答案 3 :(得分:9)
这是一个结合了Noufal和claytontstanley的解决方案,避免触及不会改变的文件。
在[alias]
文件的~/.gitconfig
块中:
psed = !sh -c 'git grep --null --full-name --name-only --perl-regexp -e \"$1\" | xargs -0 perl -i -p -e \"s/$1/$2/g\"' -
使用:
git psed old_method_name new_method_name
答案 4 :(得分:3)
是的,有。在Ubuntu中,包git-extras
提供了命令。安装它:
$ sudo apt-get install git-extras
像下面这样使用它,例如快速纠正拼写问题:
$ git sed 'qoute' 'quote'
不幸的是,它不支持像git grep那样的文件过滤器:
$ git grep -e 'class' -- '*.py'
Mac和其他操作系统上也存在相同的功能。查看其installation page。
答案 5 :(得分:2)
对提供的大多数其他解决方案(基本上只是git跟踪文件上的字符串替换)不满意,我编写了自己的脚本:git-sed。
git sed '1{/^$/d}'
)git sed 's/foo/bar' src tests
)中的一部分路径上运行git sed -e 's/foo/bar' -e '/bar/d'
)。只需将其放在PATH
中的任何位置即可使用它,或添加指向完整路径的别名。
答案 6 :(得分:1)
请注意,从git 2.1 (Q3 2014)开始,您可以为git grep
默认设置“full-name
”。
(commit 6453f7b提供Andreas Schwab)
“
git grep
”了解grep.fullname
个配置变量,强制“--full-name
”为默认值。
这可能会导致脚本用户的回归不期望这种新行为。
这意味着之前的解决方案可以从中受益:
git config grep.full-name true
并使用:
psed = !sh -c 'git grep --null --name-only --perl-regexp -e \"$1\" | xargs -0 perl -i -p -e \"s/$1/$2/g\"' -
答案 7 :(得分:0)
请参阅github上的git-search-replace - 它是为此而设计的。
答案 8 :(得分:0)
我写了一个支持文件过滤的git sed:
#!/bin/bash
split=$(($# + 1))
for i in $(seq 1 $#); do
if [[ "${!i}" = "--" ]]; then
split=$i
fi
done
git ls-files -z "${@:$split:$#}" | xargs -0 sed -b -i "${@:1:$(($split - 1))}"
(您可能不希望在非Windows平台上使用-b
参数;在Windows上必须保留Windows风格的换行符。)
然后您可以在.gitconfig
中添加别名:
[alias]
sed = ! <path to git-sed>
以便您可以像git sed -e <your expression> -- <path filter>
一样使用它。