2017-04-15 115 views
1

我偶然發現了一個奇怪的現象,據我可以告訴可以可靠地使用這個劇本我寫轉載:國家和去除

#!/bin/bash 
rm -Rf repo 
mkdir repo 
cd repo 
git init 
mkdir folder 
echo a > folder/a 
echo b > folder/b 
git add . 
git commit -m "First commit." 
rm folder/b 
echo c > folder/c 
git add . 
git commit -m "Second commit." 
cd folder 
git checkout `git log --pretty=format:%H | tail -1` . 
echo "###################################################################" 
git status 
echo "###################################################################" 
rm * 
git checkout `git log --pretty=format:%H | head -1` . 
echo "###################################################################" 
git status 
echo "###################################################################" 
git add . 
echo "###################################################################" 
git status 
echo "###################################################################" 

的哈希值是隻是更容易查看一個git status結束,另一個開始。我把它放在引擎收錄,所以我們可以參考行號更容易:https://pastebin.com/z8GgDpfw

它的輸出是:

$ ./script.sh Initialized empty Git repository in /[...]/repo/.git/ 
[master (root-commit) 165986a] First commit. 
2 files changed, 2 insertions(+) 
create mode 100644 folder/a 
create mode 100644 folder/b 
[master 241e479] Second commit. 
2 files changed, 1 insertion(+), 1 deletion(-) 
delete mode 100644 folder/b 
create mode 100644 folder/c 
################################################################### 
On branch master 
Changes to be committed: 
    (use "git reset HEAD <file>..." to unstage) 

    new file: b 

################################################################### 
################################################################### 
On branch master 
Changes to be committed: 
    (use "git reset HEAD <file>..." to unstage) 

    new file: b 

Changes not staged for commit: 
    (use "git add/rm <file>..." to update what will be committed) 
    (use "git checkout -- <file>..." to discard changes in working directory) 

    deleted: b 

################################################################### 
################################################################### 
On branch master 
nothing to commit, working directory clean 
################################################################### 

b如圖同時添加和無緣無故刪除:這是完全一樣的在回購,索引和工作樹中。 git add .魔法清理git status

這是預期的行爲?如果是這樣:爲什麼?爲什麼不只顯示一個乾淨的git status而不需要git add .必須先執行?

+0

您是否可以縮短命令以僅顯示相關的輸出,即文件既存在又被刪除的部分?另外,你介意寫一切都明確(沒有反引號)嗎? – AnoE

+0

@AnoE最好有完整的命令來重現問題。它幫助我非常瞭解發生了什麼。 – Schwern

+0

@AnoE大部分的輸出都顯示了這一點。 backtick命令找出提交ID。這些在腳本的每次執行上都不同,因爲這些執行發生在不同的時間,並且具有其中不同人的姓名和電子郵件地址(取決於運行的計算機的git配置)。如果我把我的提交散列在那裏,它不會在你的計算機上工作。 –

回答

2

你所做的是將一個新文件添加到暫存區域,然後從工作副本中刪除它。這很容易複製。

$ git init repo 
Initialized empty Git repository in /Users/schwern/tmp/repo/.git/ 
$ cd repo/ 
$ touch this 
$ git add this 
$ rm this 
$ git status 
On branch master 

Initial commit 

Changes to be committed: 
    (use "git rm --cached <file>..." to unstage) 

    new file: this 

Changes not staged for commit: 
    (use "git add/rm <file>..." to update what will be committed) 
    (use "git checkout -- <file>..." to discard changes in working directory) 

    deleted: this 

touch this創建工作副本的文件。 git add this將其複製到暫存區。 rm this從工作副本中刪除該文件,但它仍處於暫存區域

如果我現在git committhis將承諾,儘管它從工作副本中丟失。 git commit將暫存區中的內容變爲提交。

大多數時候你不需要擔心暫存區域,但當你不得不將複雜的改變分解爲多個提交時,它很容易變得10非常方便。像git add -p這樣的命令成爲創建更小,更集中的提交的非常強大的工具。


什麼你正在運行到的是「工作副本」和「臨時區域」(也稱爲「指數」或「緩存」)之間的差異。工作副本是磁盤上的實際文件,如folder/b

暫存區域是下一個提交構建的地方。你可以把它想象成一個臨時目錄。 git add將工作副本中的文件複製到臨時區域。 git commit將在暫存區域中進行任何操作並將其轉換爲下一個提交。

這就是爲什麼您可以對同一文件進行「暫存」和「非暫存」更改的原因。這意味着臨時區域中的版本與磁盤上的版本不同,該版本與以前提交(HEAD)中的版本不同。

+0

這不是發生了什麼事。執行第14行後(請參閱行號編號的pastebin鏈接),分段區域是乾淨的。顯示該現象的'git status'發生在第25行第14行之後的'git add'之前的第23行。 –

+0

啊,第16行自動將結帳引起的變化添加到登臺區域,右? –

+0

@ UTF-8是的,第一個'git checkout'相當於從舊提交重新創建b,然後將其添加到暫存區域。 'rm *'正在刪除工作副本*中的所有文件*,但是暫存區中的b被單獨保留。第二個'git checkout'將a和c帶回,但不是b。部分困惑可能是因爲有幾種不同形式的'git checkout'。你正在使用'git checkout [-p | --patch] [] [ - ] ...'這個形式與其他人非常不同。 – Schwern