以下部份翻譯ProGit 中文版v1 / 英文版v2, 加上自己一些測試。
In a DVCS, client don't just check out the latest snapshot of the files; they fully mimrror the repository.
Thus if any server dies, any of the client repositories can be copied back up to the server to restore it.
Every clone is really a full backup of all the data.
Every time you commit, or save the state of your project in Git, it is basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.
To be efficient, if files not changed, Git doesn't store the file again, just a link to the previous identical file it has already stored.
術語專有名詞要記, 這樣log, command才看的懂
Git has three main states that your files can reside in: committed, modified, and staged.
Committed: the data is safely stored in your local database.
Modified: you have changed the file but have not committed it to your database yet.
Staged: you have marked a modified file in its current version to go into your next commit snapshot.
This leads us to the three main sections of a Git project: the Git directory, the working directory, and the staging area
Git directory is where Git stores the metadata and object database for your project. it is what is copied when you clone a repository from another computer.
Working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the git directory and placed on disk for you to use or modify.
工作目錄是專案被取出的某一個版本。 這些檔案從Git目錄內被壓縮過的資料庫中拉出來並放在磁碟機供讀者使用或修改。
Staging area(暫存區) is a file, generally contained in your Git directory, that stories information about what will go into your next commit. it's sometimes referred to as the "index", but it's also common to refer to it as the staging area
暫存區域是一個單純的檔案,一般來說放在Git目錄,儲存關於下一個提交的資訊。 有時稱為索引(index)
在Git help doc中, 都會稱做像是working tree, index tree這樣。
git config
:
$ git config --global user.name "Lu Cho-Ching"
$ git config --global user.email choching.work@gmail.com
$ git config --global core.editor vim
~/.gitconfig
global 設定所在檔案:
[user]
name = Lu Cho-Ching
email = choching.work@gmail.com
[core]
editor = vim
.git/config
local設定所在檔案:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[branch "master"]
[remote "origin"]
url = git@github.com:luchoching/myJblog.git
fetch = +refs/heads/*:refs/remotes/origin/*
git config -l
列出global + local設定
git init
: initializing a repository in an existing directory
git clone
: getting a copy of an existing Git repository
The lifecycle if the status of your files:
git clone
某個repository回來的情況:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
所有檔案都是被追縱(tracked) 並且未修改的(unmodified), 因為都還沒有檔案開始修改新增, 所以: working directory clean.
如果新增一個檔案:
$ echo "a" > a.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
a.txt
nothing added to commit but untracked files present (use "git add" to track)
會告知該檔案屬於untracked files。
git init
後的git status如下:
$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
新增一個檔案的git狀態:
$ echo "my project" > README
$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
提示目前有untracked files。
Untracked
意思代表說Git有看到這個檔案, 但是這個檔案在先前的snapshoot(commit)還沒有出現過。
除非我們明確的告訴Git要commit
snapshots, 不然Git不會主動做這件事情, 主要就是避免我們把不必要包含的檔案commit進去snashoot(例如binary files)
$ git add README
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
這時候檔案被歸類在Changes to be committed
, 也就是staged
(暫存)的狀態, 這個檔案已經被暫存起來, 若這個時候執行git commit
, 那這個時候的這個檔案的版本將會被加到新的snapshoot中。
git add
可加檔案或是目錄。
$ echo "123" >> README
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
歸類為Changes not stagged for commit
的表示在這working direcoty的檔案已經被追縱(tracked)應並且已經被修改(modified), 但是還沒被暫存(staged)
注意這個時候commit的話, 就會把我們最後git add
的內容commit,而不是把現在在working directory看到的結果commit。
再度git add
就會把修改過的內容暫存:
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
git add
為多用途指令, 可以用來tracking new files, stage files, 也可以用來處理merge檔案問題, 所以要把git add
當作是add this conetent to the next commit, 而不是把這個檔案加到project中
可以git add file1, file2...
, git add dir
, git add .
git add -p
可以讓我們逐步選擇哪個檔案要add, 並且會列出差異讓我們判斷。
??
表示untracked new file, A
表示stagged new file, 紅色M
表示tracked,但修改內容還未staged, 右邊綠色M
表示tracked, 修改內容也已經staged
# no .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in the build/ directory
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory
doc/**/*.pdf
git status
顯示:
git diff
顯示:
git diff
比較我們在working directory跟staging area的檔案, 結果告知哪些行改變了但還沒staged:
$ git diff
diff --git a/Rakefile b/Rakefile
index 8f94139..f14abb9 100644
--- a/Rakefile
+++ b/Rakefile
@@ -2,6 +2,8 @@ require 'rubygems'
Gem::manage_gems
require 'rake/gempackagetask'
+test = 1
+
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "simplegit"
git diff --stat
僅列出摘要:
$ git diff --stat
Rakefile | 2 ++
1 file changed, 2 insertions(+)
git diff --staged
顯示我們目前staged 和最後的commit的差異。 例如:
$ git status
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README
modified: a.txt
狀態顯示README和a.txt都修改但修改的部份還沒staged, 利用git diff
:
$ git diff
diff --git a/README b/README
index 330ce48..53d07a8 100644
--- a/README
+++ b/README
@@ -1,3 +1,4 @@
my project
123
abc
+1q2w
diff --git a/a.txt b/a.txt
index 72943a1..730873b 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
aaa
+567
那git add README
, git diff
剩下顯示a.txt:
$ git add README
$ git diff
diff --git a/a.txt b/a.txt
index 72943a1..730873b 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
aaa
+567
繼續察看README staged和上次commit的差異:
$ git diff --staged README
diff --git a/README b/README
index 264e6ae..53d07a8 100644
--- a/README
+++ b/README
@@ -1,2 +1,4 @@
my project
123
+abc
+1q2w
git diff --word-diff
:
[-delay(1000);-]{+delay(3000);+} // wait for a second
git diff
:
- delay(1000); // wait for a second
+ delay(3000); // wait for a second
當我們的staging area已經調整到我們想要的結果了,就可以commit changes(提交變更的部份)。
所有都還沒有git add
的內容都不會commit。
$ git commit -m 'remove 2 lines'
[master 6e4bee4] remove 2 lines
1 file changed, 2 deletions(-)
訊息顯示commit到mater分支, SHA-1檢查碼(6e4bee4), 改了多少檔案, 有幾行被新增刪除
每次我們執行一次commit, 我們就紀錄了一個我們專案的snapshot, 可以用來回復或是比對之前之後的紀錄。
git commit -a
: commit a snapshot of all changes in the working directory. (不包含新增檔案)
commit messaage很重要 , How to Write a Git Commit Message 做了很詳細的提醒(more!)
要從Git移除一個檔案, 必須要從你的tracked file中移除。更明確的說, 就是從你的staging area中移除, 並且執行commit。
git rm
會將這個檔案從working directory中移除, 因此下回你也不會看到這個檔案作為untracked file 出現!
例如:
$ git rm README
rm 'README'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: README
$ git commit -m 'del README again'
[master b8cf1eb] del README again
1 file changed, 1 deletion(-)
delete mode 100644 README
當執行git rm README
的時候, README已經從working directory刪除了, README的狀態會被歸類為Changes to be committed
, 我們必須要git commit
讓這個修改紀錄commit到snapshot中。
那我們先刪除(rm README
)某檔案(也就是將該檔案從working directory中移除)的話:
$ rm README
$ git status
On branch master
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: README
這個檔案會被歸類為Changes not staged for commit
, 必須執行git rm README
或是git add README
:
$ git rm README
rm 'README'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: README
下一次commit時, 該檔案就會消失不再追蹤。
例如:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: d.json
$ git rm d.json
error: the following file has changes staged in the index:
d.json
(use --cached to keep the file, or -f to force removal)
要git rm
的時候會告知該檔案已經在stage, 真的不想要,就使用git rm -f
來強制移除:
$ git rm -f d.json
rm 'd.json'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: d.json
這樣避免不小心把已經stage但是還未commit到snapshot的檔案誤殺了。
也就是說, 我想把檔案保留在硬碟裡, 但是不再讓Git追蹤它。
使用git rm --cached d.json
:
$ git rm --cached d.json
rm 'd.json'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: d.json
Untracked files:
(use "git add <file>..." to include in what will be committed)
d.json
會發現d.json
檔案還保留在working directory ,但是歸類為Untracked files
, 另外Changes to be committed
這邊也有deleted: d.json
的紀錄提供commit, 方便日後復原。
$ git mv file_from file_to
例如:
$ git mv a.txt aa.txt
$ gss
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: a.txt -> aa.txt
How to Write a Git Commit Message