2016-09-23 49 views
-3

請原諒我的無知......這裏是背景:我創建了一個TestScritps目錄來組織測試腳本。我將三個腳本從<root dir>移到<root dir>/TestScripts。我每次移動一個,並在每個之後執行一次本地提交。然後我推動了所有的變化。'git mv'爲什麼不移動文件?如何使其「正常」行爲?

我去到另一臺機器,並進行了拉:

$ cd cryptopp/ 
$ git pull 
remote: Counting objects: 25, done. 
remote: Compressing objects: 100% (24/24), done. 
remote: Total 25 (delta 11), reused 0 (delta 0), pack-reused 0 
Unpacking objects: 100% (25/25), done. 
From https://github.com/weidai11/cryptopp 
    2ac9ea1..2a22a84 master  -> origin/master 
Updating 2ac9ea1..2a22a84 
Fast-forward 
TestScripts/cryptest-android.sh | 44 + 
TestScripts/cryptest-ios.sh  | 40 + 
TestScripts/cryptest.sh   | 5729 +++++++++++++++++++++++++++++++++++++++ 
rijndael.cpp     | 2 +- 
setenv-android.sh    | 85 +- 
5 files changed, 5870 insertions(+), 30 deletions(-) 
create mode 100755 TestScripts/cryptest-android.sh 
create mode 100755 TestScripts/cryptest-ios.sh 
create mode 100755 TestScripts/cryptest.sh 

$ ls *.sh 
cryptest-android.sh cryptest.sh  setenv-android.sh setenv-ios.sh 
cryptest-ios.sh  rdrand-nasm.sh setenv-embedded.sh 

通知文件只複製;他們沒有被移動。

我檢查了git-mv man page,但錯誤的行爲似乎沒有討論。

我有兩個問題。爲什麼git mv只複製文件,而不是移動它們?如何讓git mv「正常」執行?在這裏,「通常」意味着幾乎每個使用命令行的人都期望 - 它將文件從<target location>移動到<destination location>


這裏是相關的命令歷史。

994 rm -rf cryptopp/ 
    995 git clone https://github.com/weidai11/cryptopp 
    996 cd cryptopp/ 
    997 mkdir TestScripts 
    998 git mv cryptest.sh TestScripts/ 
    999 ls *.sh 
1000 git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)" 
1001 ls *.sh 
1002 git mv cryptest-ios.sh TestScripts/ 
1003 git commit TestScripts/cryptest-ios.sh -m "Organize test scripts (Issue 303)" 
1004 ls *.sh 
1005 git commit 
+1

你從'git status'得到了什麼? – Amit

+0

在原始機器上執行的命令的確切順序是什麼? –

+0

@Amit - 在執行移動的機器上:***'您的分支與'origin/master'是最新的。「***但是,我刪除了克隆並重新克隆。我發現它有時要求Git不要破壞它的索引文件。當發生這種情況時,我甚至無法切換分支機構,因此我們不惜一切代價盡力避免這種情況。副本和動作似乎經常會打破Git,所以我在手術後就這樣做了。 – jww

回答

3

git pull的輸出結果中可以看出,這些文件沒有被刪除。

當你做了例如爲:

git commit TestScripts/cryptest.sh -m "Organize test scripts (Issue 303)" 

雖然Git是通常約爲跟蹤文件運行良好,國內此舉被記錄爲刪除一個文件,並創建一個新的相同的一個。您承諾新文件不是從原始位置刪除文件,從而使它看起來像Git剛剛複製文件。

在未來,它通常是一個好主意,離開了從commit命令的文件名:

git commit -m "Organize test scripts (Issue 303)" 

你可以做git status事先看到什麼將被提交,並根據需要進行修改。

一個完整的會話可能是這樣的:

$ git mv cryptest.sh TestScripts/ 
$ git status 
On branch master 
Changes to be committed: 
    (use "git reset HEAD <file>..." to unstage) 

     renamed: cryptest.sh -> TestScripts/cryptest.sh 

$ git commit -m "Organize test scripts (Issue 303)" 
$ git status 
On branch master 
nothing to commit, working directory clean 
$ ls cryptest.sh 
ls: cannot access cryptest.sh: No such file or directory 
$ ls TestScripts/cryptest.sh 
TestScripts/cryptest.sh 

要解決,做到:

git rm cryptes*.sh 
git commit 

如果你想修復你的歷史,而不是,你可以這樣做:

git rebase -i HEAD^3 

並更改相關通信的命令其從pickedit。在每一站,這樣做:

git rm <file> 
git commit --amend 
git rebase --continue 

哪裏<file>是當前的原始文件。

請注意,這將重寫您的歷史記錄,因此在機器之間移動時可能會導致問題。


注意,它不應該是必要刪除並重新克隆一個Git回購,所以如果你在未來陷入困境,這是更好地嘗試解決其根源問題。 (Search aroundask here如果您需要幫助!)

+0

謝謝斯科特。我如何讓Git按預期行事?我希望'git mv'能夠實際上做自由世界中每個人移動文件時所期望的。 – jww

+0

@jww更新了我的答案。 –

+0

謝謝Scott。我認爲我們正在遭受脫節(由於我的無知;我的道歉)。我不需要重寫歷史或任何幻想。試圖做花哨巧妙的事情會讓我的生活複雜化,並從我的主要任務中解脫出來。這就是爲什麼我刪除並重新開始。爲了將來的參考,當我執行'git mv ...; git commit ...; git push',我如何確保移動發生而不是副本?我能告訴Git的只有副本;它不會移動。有沒有真正移動文件的*「真實」*移動命令? – jww

2

問題出在您(ab)使用git commit命令。

git mv確實移動文件,因爲它應該。我說,我有一個文件,叫做a回購,我想把它移到爲b:現在

$ git mv a b 
$ git status 
On branch master 
Changes to be committed: 
    (use "git reset HEAD <file>..." to unstage) 

    renamed: a -> b 

$ ls 
b <-- Only b exists here, no a 

此舉被記錄在索引中,但尚未提交。要創建提交,我做的:

$ git commit -m "Move a as b" 

不過,你所做的是:

$ git commit b -m "Move a as b" 
[master b275677] Move a as b 
1 file changed, 0 insertions(+), 0 deletions(-) 
create mode 100644 b 

當你給一個文件名作爲參數傳遞給git commit它只包括,而不是在提交上市文件,記錄當前的索引。

從內部看,git並不理解什麼是移動。它理解一個文件被創建,並且另一個文件被刪除。用於顯示歷史記錄的工具(例如,git log)將這兩部分信息組合在一起,並將文件顯示爲已移動。但是,當您指定只有新創建的文件應該包含在提交中時,它並沒有記錄舊文件的刪除,所以當您從另一臺機器上拉出時它不會顯示爲移動。

因此,您的問題的答案:「爲什麼'git mv'不移動文件?如何使其」正常「行爲? - 它確實移動了一個文件,但是你明確告訴git只提交新文件的創建,而不是刪除舊文件。爲了使其正常工作,不要這樣做 - 相反,發出git commit而沒有文件名作爲參數。

+0

謝謝。 *「你明確告訴git只提交新文件的創建」* - 實際上,我告訴Git移動一個文件;不添加或刪除。它在幕後做的是它的業務。移動之後,文件系統上只有一個文件(請參閱'ls'命令)。那是我承諾的那個。如果Git在文件系統上留下了兩個文件,那麼我會告訴git在兩個文件上都做些什麼。有沒有辦法讓Git正常運行? – jww

+1

是的,你告訴git移動一個文件,它確實如此。但是,然後你告訴它不承諾整個行動,但只承諾創建新文件。爲了使其「行爲正常」,不要這樣做。 – 1615903