簡體   English   中英

如何還原git checkout主體?

[英]How to revert a git checkout masTER?

我在測試分支上,但我誤會了

git checkout masTER

它將我的主分支重命名為masTER。 當我運行git branch ,我獲得:

masTER
test

如果我運行git checkout test ,然后運行git checkout master master分支不會檢​​索其原始大小寫。

我該如何糾正這個錯誤,為什么會發生呢?

PS:我使用git版本2.7.4(Apple Git-66)

P.S2:我正在使用OS X 10.11.6,該操作系統使用Journaled HFS +,並且默認情況下不區分大小寫。 如果我運行:

touch abc
touch abC

運行ls ab*僅給出

abc

定義問題

在任何保留大小寫但不區分大小寫的文件系統上都會發生此問題。 然后,默認情況下,它發生在Mac和Windows機頂盒上,而不發生在Linux等設備上。

Git本身是區分大小寫的,幾乎到處都是。 名為master.txt的文件獨立於一個名為masTER.txt ,因此Git 對象會將兩者保留為單獨的項目,而Git的索引(也稱為緩存或暫存區)將考慮這些單獨的文件。 git config有一個core.ignoreCase設置,旨在幫助其識別底層操作系統何時存在分歧,但總的來說,Git認為它們是不同的。

由於這些文件名存儲在文件內部( 樹型存儲庫對象存儲在.git/objects/ ,而Git索引存儲在.git/index 1中) ,而不僅僅是移交給OS進行存儲,它們可以 ,因此,區分大小寫,即使操作系統不是這樣。 2

對於分支名稱以及遠程跟蹤分支和標記名稱也是如此。 由於這些名稱保存在文件.git/packed-refs ,因此它們區分大小寫。 (Git還將其當前分支的想法以文本字符串形式存儲在.git/HEAD ,因此區分大小寫。)但是這些名稱並不總是保留在.git/packed-refs 實際上,它們通常根本不在 .git/packed-refs中。 活動分支名稱(正在被修改的分支名稱)最終存儲在.git/refs/heads/中的單個文件中,例如.git/refs/heads/master 活動的遠程跟蹤分支名稱以.git/refs/remotes/ .git/refs/remote/origin/master ,例如.git/refs/remote/origin/master

如果操作系統不區分大小寫,則意味着打包后的名為mastermasTER分支是不同的 ,但是一旦它們變為活動狀態,它們就會變得相同

不過,情況變得更糟。 無效的名稱將被打包:移入.git/packed-refs 如果名稱現在變得活躍,出現在雙方 .git/packed-refs (假設它是一個分支名) .git/refs/heads/ 這意味着不活動的名稱區分大小寫,而活動的名稱不區分大小寫,並且您可以同時發生這兩種情況,因此您的masTERmaster會有所不同(因為兩者都出現在.git/packed-refs ,我們可以區分它們) ,同時,相同! 這意味着,當如何你在這個離奇Schrödinger's貓3是Git的表現情況,是根本不清楚。 顯然,這是一個壞主意。 (我通過執行git pack-refs --all然后是git checkout -b masTER ,使測試masTER進入了既擁有master masTER git checkout -b masTER 。不過,我沒有進一步推動它。)

修復它

今天提出問題的OS( 不區分大小寫,保留 大小寫 )(再次參見腳注2)。 這意味着,一旦有了一個名為masTER的文件,嘗試使用或創建一個名為masterMasterMASTERmAsTeR等等的文件,所有這些都將引用現有文件masTER 4

其中一些操作系統允許您僅通過大小寫更改來重命名文件(例如,使用mv masTER master ),因此,如果Git只是發出操作系統級別的“重命名”操作,則git branch -m masTER master 可以解決問題。 las,實際上,Git首先進行檢查,發現它可以訪問名為master的分支(當然,這是名為masTER的文件):

$ git branch -m masTER master
fatal: A branch named 'master' already exists.

因此,解決方法是兩次重命名分支。 首先,我們將其移動到一個名字,該OS 無法找到,不符合任何現有的情況下,折疊分支名稱。 您可以選擇任何不太可能的名稱,希望它沒有被使用,或者您可以運行git branch (或git for-each-ref refs/heads )來檢查您剛剛選擇的不太可能的名稱是否確實在使用中。 無論如何,如果將當前(錯誤大小寫)分支重命名為not的新未使用名稱,即使在愚蠢的大小寫折疊規則下,也要匹配一些現有名稱,這將作為副作用,刪除舊的錯誤名稱-case-OS完全堅持匹配的名稱:

$ git branch -m masTER tmp

現在已經徹底消除了舊的“ wrong-case-but”名稱, 現在您可以使用正確的大小寫重新命名分支:

$ git branch -m tmp master

請注意,這也要注意從.git/packed-refs刪除錯誤大小寫的名稱(如果它在那里)。


1這些路徑只是默認路徑。 新的Extra-worktree功能有時會在其中找到某些文件的地方發生更改,並且Git具有可以覆蓋其中一些文件的環境變量。

2從技術上講,現代OS在每個文件系統的基礎上而不是在全局范圍內進行區分大小寫。 因此,如果顯示“如果操作系統為case-X”,則可以在頭腦中替換為“如果我使用的文件系統為case-X”。

他們可能會弄錯。 考慮德語,其中“straße”(街道)一詞以小寫形式寫成,但大寫時變成“ STRASSE”。 如果我們一次將一個字符與不區分大小寫的字符比較進行比較,則在碰到eszetß時會遇到問題,因為它會轉換為一個而不是兩個大寫S-es。

這個Python3會話表明MacOS確實不相信ß= SS:

>>> s
'straße'
>>> with open(s, 'w') as stream:
...     stream.write('street\n')
... 
7
>>> os.listdir()[10]
'file_абвгде'          # oops, that's one I was using for testing proftpd
>>> os.listdir()[30]   # should clean out my tmp dir more often ...
'straße'
>>> open('STRASSE')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'STRASSE'
>>> open('STRAßE').read()
'street\n'

這樣的事情有時使我確信計算機永遠不應該與人互動,反之亦然。 :-)

3 親愛的,你對貓做了什么? 看起來半死了! -薛定ding的妻子

4個不區分大小寫的較舊的OS(當時實際上是整個OS)將所有名稱僅折疊為一個大小寫,且總是大寫。 因此,要求創建masTER實際上代替創建MASTER 這至少和保留案例的折疊一樣錯誤。 但是,它不那么令人困惑:您至少可以說出操作系統將如何處理您的數據。 當然,案件的選擇是相當大聲的。 誠然,在僅使用大寫字母的老式電傳打字機時代,他們有借口。

我用以下方法恢復了情況:

git branch -m master tmp
git branch -m tmp master

但是仍然沒有解釋為什么會發生這種情況。

暫無
暫無

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

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