[英]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
。
如果操作系統不區分大小寫,則意味着打包后的名為master
和masTER
分支是不同的 ,但是一旦它們變為活動狀態,它們就會變得相同 !
不過,情況變得更糟。 無效的名稱將被打包:移入.git/packed-refs
。 如果名稱現在變得活躍,出現在雙方 .git/packed-refs
和 (假設它是一個分支名) .git/refs/heads/
。 這意味着不活動的名稱區分大小寫,而活動的名稱不區分大小寫,並且您可以同時發生這兩種情況,因此您的masTER
和master
會有所不同(因為兩者都出現在.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
的文件,嘗試使用或創建一個名為master
, Master
, MASTER
, mAsTeR
等等的文件,所有這些都將引用現有文件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.