2017-02-15 116 views
1

背景:我們目前有一個項目,它需要將多個git存儲庫克隆到一個父文件夾中。我試圖寫一個腳本,這樣我可以運行git操作,所有子目錄,使其更易於管理(如./gitall.sh status/add/reset/commit -m "Foobar"/push /等Shell腳本>雙引號參數,只有它存在

腳本運作良好所有操作,直到我試圖執行一個./gitall.sh push

我收到錯誤fatal: remote part of refspec is not a valid name in爲每個目錄,因爲有效的命令是git -C somedir push "" "" "" ""git borks在後雙引號)。NB的參數需要用雙引號,以便捕獲參數rs與空格。

gitall.sh

find ./repo-* -type d -depth 0 -exec bash -c "git -C {} \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" \; 

反正是有雙引號的參數,只有當它的存在? (或者無論如何告訴git忽略尾部雙引號?)

+1

如果你有這麼多的git倉庫需要自動與它們進行交互,你可能想重新考慮你的倉庫結構。 [考慮子模塊](https://git-scm.com/book/en/v2/Git-Tools-Submodules)。 – Schwern

+0

如果您發現自己需要同時提交*多個存儲庫*,那麼您使用的是Git錯誤。如果您在多個存儲庫中有更改,並且它們在語義上屬於一起以便您想將它們提交到一起,那麼它們不應該放在不同的存儲庫中。如果你有獨立的存儲庫,那些應該獨立工作*,而不需要另一個存儲庫來了解它的歷史。 – poke

+0

謝謝大家!這是我最終使用的。 https://gist.github.com/nickgrealy/3ad1d08a5efc4696a29c658f1842d89a#file-git-sh –

回答

2

問題是你正在向git push傳遞額外的參數。每個""由shell傳遞到git,然後它認爲它獲得7個參數,但最後4個是空字符串。

你在找什麼是"[email protected]""[email protected]"相當於"$1" "$2" ...

有沒有必要所有的額外報價,也沒有bash -c。將在shell腳本中展開"[email protected]"

另請注意,調用find將不能用於GNU查找,因此請使用BSD查找的完整路徑。

#/bin/sh 

/usr/bin/find ./repo-* -type d -depth 0 -exec git -C {} "[email protected]" \; 
+0

[永遠不要解析ls的輸出](http://mywiki.wooledge.org/ParsingLs)。它會例如目錄名稱包含空格時會失火。 –

+0

@SirAthos對,謝謝。必須有一種更簡單的方法來遍歷shell中的目錄。 – Schwern

1

"[email protected]"後,並有更好的方法可以做到你在做什麼:

find -name .git -prune -execdir git "[email protected]" \; 

,你可以添加-maxdepth 1或任何限制find命令的進一步洞穴探險。

3

在bash中傳遞未知數量參數的正確方法是使用"[email protected]"。此外,您不需要明確呼叫bash,因爲這會使您需要引用參數的方式複雜化。

這將自動引用所有參數:

#!/bin/bash 
find ./repo-* -type d -depth 0 -exec git -C {} "[email protected]" ';' 

往前多走一步,就沒有必要調用find如果你想要的是在目前的水平目錄條目。該/在匹配模式的結尾將只選擇目錄:

#!/bin/bash 
for d in repo-*/; do 
    [ -d "$d" ] && git -C "$d" "[email protected]" 
done 

(請注意,如果你沒有匹配模式的任何目錄,循環將使用該文本參數repo-*/執行一次;在這種情況下,[ -d "$d" ]將防止git被調用)。

最後,您可能要考慮使用Google's repo tool而不是您自己的解決方案來管理多個git回購。它功能強大且易於使用。

+0

如果沒有匹配'repo - * /'它將運行'git -C repo - * /'。也許存在檢查? – Schwern

+1

@Schwern確實會;爲了完成,我添加了一個'-d'的警戒,並澄清了這個註釋。 –