git 的一些用法

###1,建立與合併分支git

1,原理:每次提交,git把版本串成一條時間線這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。github

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:shell

1-1

每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長:數據庫

當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:vim

1-2

你看,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
相關文章
相關標籤/搜索