- 本地創建一個版本庫:
$ mkdir learngit
$ cd learngit
$ pwd
/Users/michael/learngit
- 把目錄變成Git可以管理的倉庫:
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
在此目錄新建文件,並添加到git倉庫:
$ git add readme.txt
- 把文件提交到倉庫(可一次提交多個已add的文件):
$ git commit -m "wrote a readme file"
[master (root-commit) cb926e7] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
- git status 查看倉庫當前的狀態:
$ git status
# On branch master
# 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.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
- git diff 查看修改內容:
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
- 用git log可以查看提交歷史:
$ git log
commit 3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Tue Aug 20 15:11:49 2013 +0800
append GPL
commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
Author: Michael Liao <askxuefeng@gmail.com>
Date: Tue Aug 20 14:53:12 2013 +0800
add distributed
commit cb926e7ea50ad11b8f9e909c05226233bf755030
Author: Michael Liao <askxuefeng@gmail.com>
Date: Mon Aug 19 17:51:55 2013 +0800
wrote a readme file
或者
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
- 用git reflog查看命令歷史:
$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
- 使用命令
git reset --hard commit_id
滾回歷史版本:
(上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100)
$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
撤銷修改
場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file
。
場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD file
,就回到了場景1,第二步按場景1操作。
場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退(git reset --hard commit_id
),不過前提是沒有推送到遠程庫。刪除文件
Git知道你刪除了文件,因此,工作區和版本庫就不一致了,git status命令會立刻告訴你哪些文件被刪除了。
有兩個選擇:
一是確實要從版本庫中刪除該文件,那就用命令git rm file
刪掉,並且git commit;
二是刪錯了,因爲版本庫裏還有呢,所以可以很輕鬆地把誤刪的文件恢復到最新版本,git checkout -- file
;但如果修改後沒commit的文件刪除了,所做修改也就丟失了(discard changes in working directory)。
注:git checkout其實是用版本庫裏的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。添加遠程庫
先新建一個 遠程庫repo-name
要關聯一個遠程庫,使用命令
git remote add origin git@server-name:path/repo-name.git;
關聯後,使用命令git push -u origin master
第一次推送master分支的所有內容;
此後,每次本地提交後,只要有必要,就可以使用命令git push origin master
推送最新修改;從遠程庫克隆
首先cd進入目錄,git clone [email protected]:michaelliao/gitskills.git
GitHub給出的地址不止一個,還可以用https://github.com/michaelliao/gitskills.git
這樣的地址。創建與合併分支
Git鼓勵大量使用分支:
查看分支:git branch
創建分支:git branch <name>
切換分支:git checkout <name>
創建+切換分支:git checkout -b <name>
合併某分支到當前分支:git merge <name>
刪除分支:git branch -d <name>
請注意–no-ff參數,表示禁用Fast forward:加上–no-ff參數就可以用普通模式合併,合併後的歷史有分支,能看出來曾經做過合併,而fast forward合併就看不出來曾經做過合併。
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
- 解決衝突
當Git無法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。
用git log –graph命令可以看到分支合併圖。
$ git log --graph --pretty=oneline --abbrev-commit
* 59bc1cb conflict fixed
|\
| * 75a857c AND simple
* | 400b400 & simple
|/
* fec145a branch test
...
- 分支管理策略
- Bug分支
Git還提供了一個stash功能,可以把當前工作現場“儲藏”起來,等以後恢復現場後繼續工作
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
此時,工作區是乾淨(clean)的,首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master創建臨時分支:
$ git checkout master
$ git checkout -b issue-101
現在修復bug,然後提交:
$ git add readme.txt
$ git commit -m "fix bug 101"
修復完成後,切換到master分支,並完成合並,最後刪除issue-101分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 2 commits.
$ git merge --no-ff -m "merged bug fix 101" issue-101
Merge made by the 'recursive' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue-101
Deleted branch issue-101 (was cc17032).
接着回到dev分支幹活
$ git checkout dev
$ git status
用git stash list命令看看:工作現場存到哪去了
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
需要恢復一下stash ,有兩個辦法:
一是用git stash apply恢復,但是恢復後,stash內容並不刪除,你需要用git stash drop來刪除;
另一種方式是用git stash pop,恢復的同時把stash內容也刪了:
$ git stash pop
# On branch dev
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: hello.py
#
# 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.txt
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
可以多次stash,恢復的時候,先用git stash list查看,然後恢復指定的stash,用命令:
$ git stash apply stash@{0}
- Feature分支
軟件開發中,總有無窮無盡的新的功能要不斷添加進來。
添加一個新功能時,你肯定不希望因爲一些實驗性質的代碼,把主分支搞亂了,所以,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
如果要丟棄一個 沒有被合併過 的分支,可以通過git branch -D <name>
強行刪除。 多人協作
1.查看遠程庫信息,使用git remote -v;
2.本地新建的分支如果不推送到遠程,對其他人就是不可見的;
3.從本地推送分支,使用git push origin branch-name,如果推送失敗,先用git pull抓取遠程的新提交;
4.在本地創建和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name,本地和遠程分支的名稱最好一致;
5.建立本地分支和遠程分支的關聯,使用git branch –set-upstream branch-name origin/branch-name;
6.從遠程抓取分支,使用git pull,如果有衝突,要先處理衝突。標籤管理
爲了簡化commit號,發佈一個版本時,我們通常先在版本庫中打一個標籤(tag),這樣,就唯一確定了打標籤時刻的版本。
在master當前版本上打標籤:
$ git branch
* dev
master
$ git checkout master
$ git tag v1.0
可以用命令git tag查看所有標籤:
$ git tag
v1.0
對於歷史版本,方法是找到歷史提交的commit id,然後打上就可以了:
$ git log --pretty=oneline --abbrev-commit
6a5819e merged bug fix 101
cc17032 fix bug 101
7825a50 merge with no-ff
6224937 add merge
59bc1cb conflict fixed
400b400 & simple
75a857c AND simple
fec145a branch test
d17efd8 remove test.txt
...
然後
$ git tag v0.9 6224937
此時就有兩個標籤了,可`git tag` 查看
注意,標籤不是按時間順序列出,而是按字母排序的。可以用git show <tagname>
查看標籤信息:
$ git show v0.9
commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
Author: Michael Liao <[email protected]>
Date: Thu Aug 22 11:22:08 2013 +0800
add merge
...
還可以創建帶有說明的標籤,用-a指定標籤名,-m指定說明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
還可以通過-s用私鑰簽名一個標籤:
$ git tag -s v0.2 -m "signed version 0.2 released" fec145a
命令git push origin <tagname>
可以推送一個本地標籤;
命令git push origin --tags
可以推送全部未推送過的本地標籤;
命令git tag -d <tagname>
可以刪除一個本地標籤;
命令git push origin :refs/tags/<tagname>
可以刪除一個遠程標籤。
自定義Git
等待補充忽略文件
忽略文件合集A collection of .gitignore templates
在Git工作區的根目錄下創建一個特殊的.gitignore文件,然後把要忽略的文件名填進去,Git就會自動忽略這些文件。
.gitignore文件本身要放到版本庫裏,並且可以對.gitignore做版本管理!
舉個例子:
假設你在Windows下進行Python開發,Windows會自動在有圖片的目錄下生成隱藏的縮略圖文件,如果有自定義目錄,目錄下就會有Desktop.ini文件,因此你需要忽略Windows自動生成的垃圾文件:
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
有些時候,你想添加一個文件到Git,但發現添加不了,原因是這個文件被.gitignore忽略了,試着修改忽略規則,或者強制添加:
$ git add -f App.class
- 配置指令別名
用st表示status,–global參數是全局參數,也就是這些命令在當前用戶的所有Git倉庫下都有用。
$ git config --global alias.st status
很多人都用co表示checkout,ci表示commit,br表示branch:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch
- 搭建Git服務器
待補充