我在登錄時運行一個腳本,打開一個終端,並在它運行一個shell腳本讀取如何確定一個git拉是否從一個shell腳本
git pull --rebase && git log
但是做了,這個混帳日誌仍將運行如果上游沒有變化。如何修改此腳本以僅在運行git log
時發生變化?
我在登錄時運行一個腳本,打開一個終端,並在它運行一個shell腳本讀取如何確定一個git拉是否從一個shell腳本
git pull --rebase && git log
但是做了,這個混帳日誌仍將運行如果上游沒有變化。如何修改此腳本以僅在運行git log
時發生變化?
你可以做這樣的事情:
prev=$(git rev-list HEAD -n 1)
git pull --rebase
test $prev = $(git rev-list HEAD -n 1) || git log
「常規」(無--rebase
)git pull
真正運行之後git merge
git fetch
。 A git pull --rebase
確實運行git fetch
,然後是git rebase
(如果您正在重新投入使用的「跟蹤分支」本身已重新發布,那麼可以使用一些巧妙的方法)。
在這兩種情況下,它實際上是fetch
一步,在上游的變化帶來的。第二部分(合併或rebase)簡單地將這些上游更改(如果有)與您的更改(如果有)進行組合。所以你想知道的是:是否從上游跟蹤分支獲取任何東西?
janos' answer將工作得很好。爲了理解爲什麼,雖然考慮提交圖表在git pull --rebase
之前和之後的樣子。我們將用一個簡單的圖形開始只是犯A
,B
和Y
,其中A
和B
是「上」上游分支和Y
是你自己的承諾將要重建基礎:
A - B <-- origin/master
\
Y <-- HEAD=master
(假設你在分支master
和你的遠程被命名爲origin
,但因爲我們只看HEAD
它適用於任何分支和任何遠程)。
如果fetch
步驟不執行任何操作,該圖保持相同(無操作/跳過)合併或 - 底墊步驟之後。因此HEAD
仍然是master
,它仍然指代提交Y
(Y
代表那些長的SHA-1字符串之一,如43be6d8...
;這些是提交的「真實姓名」,並且它們永不改變;您不能更改提交,您只能停止看它,我們將在下面看到)。
如果fetch
步驟是在新的承諾帶來C
,雖然中間圖是這樣的:
A - B - C <-- origin/master
\
Y <-- HEAD=master
現在git pull --rebase
具有運行git rebase
複製提交你Y
到一個新的提交。現有的Y
提交保留在那裏,但標籤master
已移至指向新提交。讓我們把新的承諾Y'
因爲它的內容基本相同的Y
,它只是父-ID現在是C
而不是B
。所以,現在你有:
A - B - C <-- origin/master
. \
. Y' <-- HEAD=master
.
Y [no label - abandoned]
所以,讓我們這短短的腳本,並略微簡化它(我會扭轉測試,即使這使得它長一點,並加入雙引號):
prev=$(git rev-parse HEAD)
git pull --rebase
test "$prev" != "$(git rev-parse HEAD)" && git log
第一rev-parse
找到了SHA-1爲您HEAD
提交(Y
)。然後,我們執行git pull --rebase
,它確實或不帶來新的提交。最後,我們看到HEAD
是否指向新的不同提交(Y'
)。如果是這樣,舊的SHA-1和新的SHA-1將會不同,!=
測試會成功,我們將運行git log
。
這是值得考慮的幾個邊緣和錯誤的情況下,以及:
如果沒有提交Y
,即你的分支和上游分支保持同步?
沒問題!這裏HEAD
會發現pull
之前提交B
,並要麼找到再犯B
(無變化)或提交C
(一些變化)。測試仍然會做正確的事情。
如果在pull --rebase
失敗,因爲上游不能達到?
這導致了與上游沒有變化相同的行爲。
如果該pull --rebase
能夠獲取,但底墊失敗?
在這種情況下,您的提交(Y
)仍然是您的HEAD
提交。在這裏,腳本認爲沒有任何變化,跳過git log
...但git pull --rebase
步驟打印關於失敗的rebase的一些錯誤,所以這可能是正確的。
如果什麼也沒有HEAD
修訂? (空回購;不是在git倉庫;其他奇異誤差)
在這種情況下,git rev-parse
將因錯誤退出,prev
將被設置爲空字符串。 git pull --rebase
步驟也將失敗,第二個git rev-parse
將再次失敗。這就是爲什麼我添加了雙引號:現在我們將運行test "" != ""
。這兩個空字符串是相同的,腳本將跳過git log
步驟。所以你會得到一些額外的錯誤信息,但它仍然會工作。
(爲了使這更穩健,我們也許應該停止整個過程中,如果第一git rev-parse HEAD
失敗,但這是相對較小的。)
這裏的一個更復雜(有趣)方法是找到實際上游分支,看看會發生什麼,在fetch
步驟中執行。這將允許您記錄上游分支上做了什麼,如果有的話。事實證明,這種使用@{u}
gitrevisions語法很簡單:
old=$(git rev-parse @{u}) || exit # find current upstream, bail on error
git pull --rebase || exit # update, bail on error
new=$(git rev-parse @{u}) || exit # find new upstream, bail on error
[ $old = $new ] && exit # nothing to do if unchanged
ours=$(git rev-parse HEAD) || exit
if [ ! -z "$(git rev-list $new..$old)" ]; then
# this is pretty rare; pull --rebase knows what to do though
# could add "we rebased onto new head" if $ours != $new, perhaps
echo "upstream removed old commits:"
git log --oneline $new..$old
fi
if [ $ours != $new ]; then
echo "upstream added new commits, which we rebased onto:"
else
echo "upstream added new commits:"
fi
git log $old..$new
(注:上面的腳本是完全未經測試)。
你一定非常信任在登錄時盲目運行git pull。 –