###1,建立與合併分支git
1,原理:每次提交,git把版本串成一條時間線這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。github
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:shell
每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長:數據庫
當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:vim
你看,Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!安全
不過,從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:app
假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:編輯器
因此Git合併分支也很快!就改改指針,工做區內容也不變!fetch
合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:ui
2,實戰:
首先,咱們建立dev分支,而後切換到dev分支:
$ git checkout -b dev Switched to a new branch 'dev'
git checkout命令加上-b參數表示建立並切換,至關於如下兩條命令:
$ git branch dev $ git checkout dev Switched to branch 'dev'
而後,用git branch命令查看當前分支:
$ git branch * dev master
git branch命令會列出全部分支,當前分支前面會標一個*號。
而後,咱們就能夠在dev分支上正常提交,好比對readme.txt作個修改,加上一行:
Creating a new branch is quick.
而後提交:
$ git add readme.txt $ git commit -m "branch test" [dev fec145a] branch test 1 file changed, 1 insertion(+)
如今,dev分支的工做完成,咱們就能夠切換回master分支:
$ git checkout master Switched to branch 'master'
切換回master分支後,再查看一個readme.txt文件,剛纔添加的內容不見了!由於那個提交是在dev分支上,而master分支此刻的提交點並無變:
如今,咱們把dev分支的工做成果合併到master分支上:
$ git merge dev Updating d17efd8..fec145a Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+)
git merge命令用於合併指定分支到當前分支。合併後,再查看readme.txt的內容,就能夠看到,和dev分支的最新提交是徹底同樣的。
注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。
固然,也不是每次合併都能Fast-forward,咱們後面會講其餘方式的合併。
合併完成後,就能夠放心地刪除dev分支了:
$ git branch -d dev Deleted branch dev (was fec145a).
刪除後,查看branch,就只剩下master分支了:
$ git branch * master
由於建立、合併和刪除分支很是快,因此Git鼓勵你使用分支完成某個任務,合併後再刪掉分支,這和直接在master分支上工做效果是同樣的,但過程更安全。
###2,解決衝突
人生不如意之事十之八九,合併分支每每也不是一路順風的。
準備新的feature1分支,繼續咱們的新分支開發:
$ git checkout -b feature1 Switched to a new branch 'feature1'
修改readme.txt最後一行,改成:
Creating a new branch is quick AND simple.
在feature1分支上提交:
$ git add readme.txt $ git commit -m "AND simple" [feature1 75a857c] AND simple 1 file changed, 1 insertion(+), 1 deletion(-)
切換到master分支:
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit.
Git還會自動提示咱們當前master分支比遠程的master分支要超前1個提交。
在master分支上把readme.txt文件的最後一行改成:
Creating a new branch is quick & simple. 提交:
$ git add readme.txt $ git commit -m "& simple" [master 400b400] & simple 1 file changed, 1 insertion(+), 1 deletion(-)
如今,master分支和feature1分支各自都分別有新的提交,變成了這樣:
這種狀況下,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突,咱們試試看:
$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result.
果真衝突了!Git告訴咱們,readme.txt文件存在衝突,必須手動解決衝突後再提交。git status也能夠告訴咱們衝突的文件:
$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # # Unmerged paths: # (use "git add/rm <file>..." as appropriate to mark resolution) # # both modified: readme.txt # no changes added to commit (use "git add" and/or "git commit -a")
咱們能夠直接查看readme.txt的內容:
Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changes of files. <<<<<<< HEAD Creating a new branch is quick & simple. ======= Creating a new branch is quick AND simple. >>>>>>> feature1 Git用<<<<<<<,=======,>>>>>>>標記出不一樣分支的內容,咱們修改以下後保存: Creating a new branch is quick and simple.
再提交:
$ git add readme.txt $ git commit -m "conflict fixed" [master 59bc1cb] conflict fixed
如今,master分支和feature1分支變成了下圖所示:
用帶參數的git log也能夠看到分支的合併狀況:
$ git log --graph --pretty=oneline --abbrev-commit * 59bc1cb conflict fixed |\ | * 75a857c AND simple * | 400b400 & simple |/ * fec145a branch test ...
最後,刪除feature1分支:
$ git branch -d feature1 Deleted branch feature1 (was 75a857c).
工做完成。
###多人協做
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
要查看遠程庫的信息,用git remote:
$ git remote origin
或者,用git remote -v顯示更詳細的信息:
$ git remote -v origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push)
上面顯示了能夠抓取和推送的origin的地址。若是沒有推送權限,就看不到push的地址。
###3,推送分支
推送分支,就是把該分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:
$ git push origin master
若是要推送其餘分支,好比dev,就改爲:
$ git push origin dev
可是,並非必定要把本地分支往遠程推送,那麼,哪些分支須要推送,哪些不須要呢?
master分支是主分支,所以要時刻與遠程同步;
dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。
總之,就是在Git中,分支徹底能夠在本地本身藏着玩,是否推送,視你的心情而定!
###4,忽略特殊文件
有些時候,你必須把某些文件放到Git工做目錄中,但又不能提交它們,好比保存了數據庫密碼的配置文件啦,等等,每次git status都會顯示Untracked files ...,有強迫症的童鞋內心確定不爽。
好在Git考慮到了你們的感覺,這個問題解決起來也很簡單,在Git工做區的根目錄下建立一個特殊的.gitignore文件,而後把要忽略的文件名填進去,Git就會自動忽略這些文件。
不須要從頭寫.gitignore文件,GitHub已經爲咱們準備了各類配置文件,只須要組合一下就可使用了。全部配置文件能夠直接在線瀏覽:https://github.com/github/gitignore
忽略文件的原則是:
忽略操做系統自動生成的文件,好比縮略圖等; 忽略編譯生成的中間文件、可執行文件等,也就是若是一個文件是經過另外一個文件自動生成的,那自動生成的文件就不必放進版本庫,好比Java編譯產生的.class文件; 忽略你本身的帶有敏感信息的配置文件,好比存放口令的配置文件。 舉個例子:
假設你在Windows下進行Python開發,Windows會自動在有圖片的目錄下生成隱藏的縮略圖文件,若是有自定義目錄,目錄下就會有Desktop.ini文件,所以你須要忽略Windows自動生成的垃圾文件:
# Windows: Thumbs.db ehthumbs.db Desktop.ini
而後,繼續忽略Python編譯產生的.pyc、.pyo、dist等文件或目錄:
# Python: *.py[cod] *.so *.egg *.egg-info dist build
加上你本身定義的文件,最終獲得一個完整的.gitignore文件,內容以下:
# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
最後一步就是把.gitignore也提交到Git,就完成了!固然檢驗.gitignore的標準是git status命令是否是說working directory clean。
使用Windows的童鞋注意了,若是你在資源管理器裏新建一個.gitignore文件,它會很是弱智地提示你必須輸入文件名,可是在文本編輯器裏「保存」或者「另存爲」就能夠把文件保存爲.gitignore了。
有些時候,你想添加一個文件到Git,但發現添加不了,緣由是這個文件被.gitignore忽略了:
$ git add App.class The following paths are ignored by one of your .gitignore files: App.class Use -f if you really want to add them.
若是你確實想添加該文件,能夠用-f強制添加到Git:
$ git add -f App.class
或者你發現,多是.gitignore寫得有問題,須要找出來到底哪一個規則寫錯了,能夠用git check-ignore命令檢查:
$ git check-ignore -v App.class .gitignore:3:*.class App.class
Git會告訴咱們,.gitignore的第3行規則忽略了該文件,因而咱們就能夠知道應該修訂哪一個規則。
小結
忽略某些文件時,須要編寫.gitignore;
.gitignore文件自己要放到版本庫裏,而且能夠對.gitignore作版本管理!
###5,vim簡單操做
####正常模式 正常模式通常用於瀏覽文件,也包括一些複製、粘貼、刪除等操做。這時擊鍵時, 通常的鍵/鍵組合會被當成功能鍵,而不會鍵入對應的字符。
在這個模式下,咱們可能經過鍵盤在文本中跳來跳去,跳動的範圍從小到大是字符、 單詞、行、句子、段落和屏幕。
啓動vim後默認位於正常模式。不論位於什麼模式,按下<Esc>鍵(有時須要按兩下) 都會進入正常模式。
####插入模式 在正常模式中按下i, I, a, A等鍵(後面系列文章會詳細介紹),會進入插入模式。 如今只用記住按i鍵會進行插入模式。插入模式中,擊鍵時會寫入相應的字符。
命令模式 在正常模式中,按下:(冒號)鍵,會進入命令模式。在命令模式中能夠執行 一些輸入並執行一些vim或插件提供的指令,就像在shell裏同樣。這些指令包括 設置環境、文件操做、調用某個功能等等。
可視模式 在正常模式按下v, V, <Ctrl>+v,能夠進入可視模式。可視模式中的 操做有點像拿鼠標進行操做,選擇文本的時候有一種鼠標選擇的即視感,有時候 會很方便。
####命令模式下的簡單命令
:w 將編輯的內容寫入原始文件,用來保存編輯的中間結果 :wq 將編輯的內容寫入原始文件並退出編輯程序(至關於 ZZ 命令) :w file 將編輯的內容寫入 file 文件,保持原有文件的內容不變 :a,bw file 將第 a 行至第 b 行的內容寫入 file 文件 :r file 讀取 file 文件的內容,插入當前光標所在行的後面 :e file 編輯新文件 file 代替原有內容 :f file 將當前文件重命名爲 file :f 打印當前文件名稱和狀態,如文件的行數、光標所在的行號等
###6,一個小問題:Git warning:LF will be replaced by CRLF in readme.txt的緣由與解決方案
首先問題出在不一樣操做系統所使用的換行符是不同的,下面羅列一下三大主流操做系統的換行符:
Uinx/Linux採用換行符LF表示下一行(LF:LineFeed,中文意思是換行);
Dos和Windows採用回車+換行CRLF表示下一行 (CRLF:CarriageReturn LineFeed,中文意思是回車換行);
Mac OS採用回車CR表示下一行(CR:CarriageReturn,中文意思是回車)。
在Git中,能夠經過如下命令來顯示當前你的Git中採起哪一種對待換行符的方式
$ git config core.autocrlf
此命令會有三個輸出,「true」,「false」或者「input」
爲true時,Git會將你add的全部文件視爲文本問價你,將結尾的CRLF轉換爲LF,而checkout時會再將文件的LF格式轉爲CRLF格式。
爲false時,line endings不作任何改變,文本文件保持其原來的樣子。
爲input時,add時Git會把CRLF轉換爲LF,而check時仍舊爲LF,因此Windows操做系統不建議設置此值。
解決辦法: 將core.autocrlf設爲false便可解決這個問題
$ git config --global core.autocrlf false