我猜測了一下,但最初我相信你在提交f065234
的「分離頭部」模式,這是分支名稱master
指向的提交。因此git log --oneline
告訴你,提交和它的兩個祖先。
無論出於何種原因,在提交時,您(或您所做的)刪除了文件y.y
。
首先,讓我們進入該狀態。
$ cd /tmp; mkdir repo; cd repo
$ git init
Initialized empty Git repository in /tmp/repo/.git/
$ echo 'first file x.x' > x.x
$ git add x.x
$ git commit -m 'init commit'
[master (root-commit) 63ddf00] init commit
1 file changed, 1 insertion(+)
create mode 100644 x.x
$ echo 'second file x.y' > x.y
$ git add x.y
$ git commit -m '2nd commit'
[master 62cb693] 2nd commit
1 file changed, 1 insertion(+)
create mode 100644 x.y
$ echo 'third file y.y' > y.y
$ git add y.y
$ git commit -m 'add y.y'
[master b4c61d1] add y.y
1 file changed, 1 insertion(+)
create mode 100644 y.y
$
現在我們只需要 「分離HEAD」:
$ git checkout --detach master
Note: checking out 'master'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at b4c61d1... add y.y
$
接下來,我們刪除y.y
,並要求混帳切換到分支master
。我們將看到D
狀態文件y.y
,就像你做的事:
$ rm y.y
$ git checkout master
D y.y
Switched to branch 'master'
$
我做的原因上面的「分離HEAD」的步驟是,如果我沒有,我會體驗到不同的輸出。我可以通過只重複git checkout master
命令,現在告訴你:
$ git checkout master
D y.y
Already on 'master'
$
在這兩種情況下,雖然,這裏的事情是,Git是已經在提交你問的。因此它不必觸摸工作目錄 - 所以它不需要。
但是別的什麼!實際上,這是我的rm y.y
命令。我刪除了該文件。 Git可以看到文件丟失,所以它通過D
行宣佈。
接下來,你問的git檢查出先前的承諾(HEAD~1
又名master~1
,這是你的倉庫,我的承諾04a7340
爲62cb693
,如上面的git commit
輸出看到的,因爲我不是你,我的文件可能包含不同的數據,等等:我的存儲庫是不同的,這使得我所有的SHA-1不同)。
要切換到提交,git必須刪除文件y.y
:該文件在提交f065234
而不是提交04a7340
。該文件已經丟失,這使得git的工作非常簡單:它通過無所事事「去除」不存在的文件。
從這點上來說,如果你問的git檢查出提交master
-i.e.,提交f065234
-git將不得不把文件y.y
到工作目錄。你在一些額外的步驟(首先檢查b6ca522
,其中也沒有y.y
,然後檢查f065234
),但你到達那裏,這意味着git從底層存儲庫中重新提取y.y
,把它放在你的工作目錄中。
注:這裏要小心,git checkout
有不同的使用模式,可以輕鬆地可以擦除工作。該文檔中的模式拼寫爲git checkout commit -- path
,例如git checkout HEAD -- x.x
。不幸的是,(在我看來)很容易意外地調用這種其他的使用模式。下一節只是約git checkout commit
,而不是git checkout commit -- path
。在此之後,我會插入一個關於path
版本的簡要部分。
作爲一般規則,任何犯SHA-1你在-是否脫落,或通過分支名稱是什麼,當你問它來檢查了另一個承諾Git是看什麼文件需要通過比較兩個提交,在工作目錄中添加,刪除或修改。 (如果兩次提交相同,結果很簡單:沒有文件需要更改,請仔細考慮下面的第一條評論:如果你已經在1234567
和你git checkout 1234567
,沒有文件需要更改,所以git checkout
簡單地做git status
。)
任何工作目錄文件,不是需要任何更改,git單獨離開。
對於任何文件確實需要在某種方式進行更改,git檢查,看看你是否會失去工作。一些明顯的失去工作的方式包括這些(有更多,但我會列出這些):
- git必須刪除文件,但你已經編輯它(它不符合當前的提交,太多少於目標提交,它表示刪除它)。
- git必須用不同的版本替換文件,但你已經編輯它。
- git必須創建文件(它在目標提交中,但不是當前提交),但是你自己創建了它,其內容不同於git將要放入的文件。
在這些情況下,git checkout
將因錯誤而停止,除非你給它--force
標誌。
但是,在許多情況下,許多工作目錄文件不需要更改。例如,在上面,我可以從master
切換到master~1
或master~2
而不改變文件x.x
:這三個修訂版本都是一樣的。
這意味着git會允許我修改x.x
,甚至完全刪除它,還是看看一些其他的承諾:從開關到master
和master~1
/或後不需要進行任何更改x.x
。如果我做了這些簽出,git會打印任何這樣的文件的單行狀態消息,其中D
表示它在工作樹中缺失,或M
表示它在工作樹中被修改(相對於現在檢查-out commit或branch)。
(無論這是否是最初的設計,人們都喜歡它,它可以讓你開始改變一堆文件,然後意識到你應該一直在另一個分支上工作,所以你git checkout
另一個分支。只要沒有任何更改需要銷燬切換,git的開關,讓你的變化,所以現在這些變化都準備在其他分支去)
上述所有正在討論如何git checkout
。當你要求它簽出一個特定的提交(「分離HEAD」模式)或分支(「不分離」)時會表現出來。在這種模式下,您只需調用git checkout
,並且只有一個附加參數,它應該是分支名稱或其他提交說明符:git checkout HEAD^
,git checkout master
等等。
不管是什麼原因,git 也使用git checkout
命令從提交中提取特定文件(通過索引/暫存區寫入提取)。要調用這個模式,你應該給一個字面雙破折號--
分離git checkout
兩個或多個參數:
git checkout HEAD -- x.x x.y
這告訴git checkout
,關於--
左側的東西是犯符,即其中在存儲庫中查找 - 而右邊的東西是文件路徑,它應該丟棄在右側命名的路徑上正在進行的任何工作,用從左側提交中提取的版本替換它們。
換句話說,如果你已經開始編輯x.x
並決定要「取消編輯」,以使它看起來像它在HEAD
確實犯,你檢查出的x.x
的HEAD版本到文件x.x
。或者,如果要將x.x
的前一個(HEAD^
或HEAD~1
)版本獲取到工作目錄並進行階段提交,則可以使用git checkout HEAD^ -- x.x
。
這種形式顯然比git checkout commit
(它試圖避免破壞你的工作)更危險。不幸的是,git checkout
不是要求的--
部分。此外,如果您不提供它,則提交說明符默認爲HEAD
。所以:
git checkout -- x.x
也的意思是「請揍我發來文件x.x
的變化,也是如此:
git checkout x.x
因爲x.x
不是提交或分支同樣的名稱:
git checkout .
命名一個路徑,但這次路徑是「當前目錄」,所以這個clobbers所有的文件都工作在一個重新在當前目錄中,或者遞歸地在它下面的任何地方!
(如果混帳用於「退房特定文件」不同的命令VS它可能是好的,「退房給出提交-ID」,使其更難意外揍的工作。)
你做不問,但我也會在這裏包括這個:「分離HEAD」和「在分支上」之間的區別實際上是非常簡單的。在.git
目錄中查看;你會發現一個名爲HEAD
的文件。當您在諸如master
的分支上時,HEAD
的內容是ref: refs/heads/master
。當你分離時,內容是一個原始的SHA-1像b4c61d1692f750607a821aa53788e3a7ce5d1199
(git通常顯示你的縮寫版本)。簡而言之,當你在分支上時,git從分支名稱中獲取原始SHA-1,分支名稱在HEAD
文件中;當你分離時,git將原始SHA-1直接存儲在HEAD
文件中。
還有一個關鍵區別,它適用於創建新提交提交。如果HEAD
有一個原始SHA-1,git將新提交的SHA-1寫入HEAD
。如果HEAD
改爲ref: refs/heads/branch
,git會將新提交的SHA-1寫入分支映射文件,而文件HEAD
保持不變。爲了提高效率,分支映射文件有時會有所不同,儘管當前新的提交始終創建或更新名爲.git/refs/heads/branch
的文件。
你的git版本是什麼? –