簡體   English   中英

如何將git工作樹重置為更新的提交

[英]how to reset a git working tree to an updated commitish

我需要使用Bash腳本擴展一個給定的工具,該腳本應該可以在Linux和MacOS上使用。 該腳本獲取2個參數:

  1. 存儲庫位置(文件系統,ssh,http(s)等)
  2. 提交 ,例如分支,標記,提交哈希

我對參數沒有影響

腳本運行的結果應該是

  • 將存儲庫克隆到固定的目標位置(對於一個存儲庫始終相同)
  • 存儲庫的工作樹應對應於社區的最新狀態(例如,如果它是一個分支,則該分支的尖端)

如果該存儲庫在本地還不存在,則過程很簡單

git clone $REPO_SOURCE $REPO_DIR
cd $REPO_DIR
git checkout $REPO_REF

我的問題:考慮一個存儲庫已經克隆到/repos/foo git fetch obvios git fetch后,如何將該存儲庫更新為提供的$REPO_REF

  • 如果$REPO_REF是分支,則git checkout $REPO_REF && git pull應該起作用
  • 如果是提交哈希,則不需要更新(只需git checkout $REPO_REF嗎?)
  • 如果是標簽,則標簽可能已在原點上移動,該如何處理?
  • 如何處理其他邊緣情況?

是否有一種簡單的reset-repository-to-this-commitsh方式,所以存儲庫的行為就像是剛克隆的一樣?

側節點:

  • 相同的存儲庫可以與不同的commitish一起使用,但只能按順序使用:確保腳本不會同時被多次調用
  • 對存儲庫的所有外部更改可能總是被丟棄而無需通知
  • 雖然刪除和克隆存儲庫是可行的,但由於其大小和丑陋的解決方案,這是不切實際的
  • 無需(git)更改,因此檢出分離的頭部是可以的

唯一完全安全且方便的方法是讓另一個 Git(您可能正在克隆的一個Git,但可能沒有克隆)為您解析名稱。 然后,您具有哈希ID,並且哈希ID是通用的。

如果名稱是分支名稱或標記名稱,則可以使用git ls-remote來完成該步驟。 如果這可能是其他公式(例如master~13 ),那么您就不走運了。 因此,如果您需要在本地解析名稱:

  • 如果遵守標簽規定,則標簽將永遠不會移動。 這意味着,如果您有一個具有標簽的現有克隆,它具有正確的標簽,並且您在這里還可以,並且如果您有一個沒有標簽的現有克隆,則可以添加該標簽並對其進行解析。

  • 如果不遵守標簽規范,則必須刪除並重新創建標簽(糟糕),或者重新發明遠程標簽:將其refs/tags/*名稱復制到refs/rtags/<remote>/*命名空間。 當兩個遙控器的標簽名稱相同時,請參見Git-Checkout一個遙控器標簽

  • 如果你有一個分支名稱或東西相對於分支名稱,打開分支名到自己的遠程跟蹤名稱(例如,更換master~13refs/remotes/origin/master~13 ),並解決它。

無論如何,您現在都有一個哈希ID,並且可以使用分離的HEAD模式。

使用“標准” git克隆,您可以這樣做:

# cleanup old cruft
git reset --hard HEAD
git clean -fdx

# detach from current branch (if on any)
git checkout --detach
# delete all local branches
git for-each-ref --format="%(refname:strip=2)" refs/heads |xargs -r git branch -D
# fetch and update all remote refs and tags
git fetch --force --all --tags --prune --prune-tags
# checkout
git checkout "$COMMITISH"

這樣,您可以像往常一樣依靠git checkout來完成其工作,而無需復制其啟發式,快捷方式等任何內容。

暫無
暫無

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

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