簡體   English   中英

如何使用 bash 將多個 git 分支重命名為小寫

[英]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 branchgit for-each-ref )。 那很好。
  • 這兩個命令都需要 bash,並且在/bin/sh中不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM