[英]how to rename multiple git branches into lowercase using bash
我想用小写重命名多个分支,因为在迁移之前我们必须将所有大写分支转换为小写。 git 分支:
CPORT_121
GC_211
Lower-Upper_DEMO
现在我尝试了下面的一个,但它不起作用。
git branch | tr A-Z a-z | xargs -n 2 git branch -m
error: refname refs/heads/cport_121 not found
fatal: Branch rename failed
fatal: '*' is not a valid branch name.
这是对循环进行编码的错误方法。 (评论中的结帐循环也不是真正的正确方法。)出于脚本目的,我们应该尽可能使用git for-each-ref
,而这里完全有可能。 如果我们想为每个需要重命名的refs/remotes/origin/*
远程跟踪名称创建本地分支名称,我们将从这个开始:
git for-each-ref \
--format="%(if)%(symref)%(then)%(else)%(refname:strip=3)%(end)" \
refs/remotes/origin | sed '/^$/d' > /tmp/branchlist
这将创建一个包含所有远程跟踪名称的文件 ( /tmp/branchlist
)。 if/then/else/end
序列删除了HEAD
符号 ref 并且sed
清除了相应的空行(不是绝对必要的,但很有用)。
其中一些分支名称可能已经很好了! 我们可能不想对这些大惊小怪。 所以现在我们可以grep
大写:
LC_ALL=C grep -E '^[A-Z]+$' /tmp/branchlist > /tmp/upper
如果您的 grep 使用 POSIX 排序规则(我的至少在某些系统上使用),则此处的LC_ALL
是必需的。
现在检查/tmp/upper
以确保其中没有任何名称在/tmp/branchlist
中也显示为小写字母可能是明智的。 这是一次性手动操作,但如果您愿意,可以将其自动化:
tr A-Z a-z < /tmp/upper | grep -F -f - /tmp/branchlist
请注意,这将错误地匹配子字符串,例如,如果有一个“坏”名称OOPS
和一个“好”名称whoops
,即使它不同,也会找到“好”名称; 修复它更难,我不会打扰。
我们现在要在本地存储库中创建一个名称与大写名称匹配的小写名称分支:
awk '{ print "git branch --no-track " tolower($0) " refs/remotes/origin/" $0 }' \
< /tmp/upper
确保这会生成所需的命令,然后通过管道输入sh
:
awk '{ print "git branch --no-track " tolower($0) " refs/remotes/origin/" $0 }' \
< /tmp/upper | sh
我们已经生成了所需的分支名称。
但是,与其创建这样的分支名称,对我来说,运行直接在远程创建名称的git push
命令更有意义。
为此,我们希望:
git push origin
接下来是一系列本地远程跟踪名称和所需的分支名称:对于每个大写名称,我们想要该名称的小写版本作为分支名称。 所以那将是:
(printf "git push origin"
awk '{ printf(" %s:%s", "refs/remotes/origin/" $0, "refs/heads/" tolower($0)) }' \
< /tmp/upper
echo "")
验证这是否产生了所需的git push
命令,然后通过管道传输到 sh。
您可能希望稍后git push --delete
仅大写的名称; 现在应该很明显如何做到这一点。 之后,此存储库的其他用户可能想要运行git fetch --prune
来更新他们的远程跟踪名称。
我会尝试,但我真的很害怕这样的行为:|。 因此,请小心并确保您不会丢失数据。
# Create three random branches for the test
git branch www_FUNK0 origin/master
git branch WWW_funk1 origin/master
git branch WWW_FuNk2 origin/master
git branch | grep -i www_funk
# This is the output of this command:
# www_FUNK0
# WWW_funk1
# WWW_FuNk2
# Iterating through all WWW_FUNK* branches one by one
for b in $(git branch | grep -i www_funk | tr -d ' ')
do
# Storing the $b branch into the tmp branch and then
# delete $b branch
# and rename tmp branch to the lowercase version of $b
git checkout -B tmp $b
git branch -D $b
git branch -m ${b,,}
done
git checkout master
git branch -D tmp
git branch | grep -i www_funk
# Finally we have this result:
# www_funk0
# www_funk1
# www_funk2
请不要在包含有用数据的回购中尝试这些练习!!!
git branch --format='%(refname:short)' \
| sed -n '/[A-Z]/s/.*/git branch -m & \L&/p'
做分支; 如果您想要其他裁判,您将不得不对此更加挑剔,例如在本地更改远程跟踪名称对任何人都没有任何好处,您需要推送更新:
git for-each-ref --format='%(if)%(symref)%(then)%(else)%(refname:short)%(end)' \
refs/remotes \
| sed -nr 's,([^/]*)/(.*),git push \1 refs/remotes/&:refs/heads/\L\2,p'
然后git fetch --prune
。
使用bash ,这里有两种正确解析分支名称的方法。
简单的方法:逐行读取分支列表,依靠分支名称不能包含新行的事实:
git branch --format '%(refname:lstrip=-1)' |
while IFS= read -r name; do
git branch -m "$name" "${name,,}"
done
“正确”方式:使用git for-each-ref
和--shell
选项安全地引用每个名称,以便可以eval
编辑。 可以将带引号的名称添加到数组中,以循环:
eval "names=($(
git for-each-ref refs/heads \
--format '%(refname:lstrip=-1)' \
--shell
))"
for name in "${names[@]}"; do
git branch -m "$name" "${name,,}"
done
refs/heads
)中去除父目录。git branch
,它也只打印名称,没有前导空格和星号。${name,,}
是 bash 语法,用于小写变量中的所有字符。refs/heads/branch-name
以包含新行,git 拒绝列出该分支并打印损坏的名称错误(对于git branch
和git for-each-ref
)。 那很好。/bin/sh
中不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.