用好git

git分支開發,合併,回退等的基本操作:

一、版本回退:

$ git log

查看提交歷史。

$ git reset --hard 1094a

Git的版本回退速度非常快,因爲Git在內部有個指向當前版本的HEAD指針,Git僅僅是把HEAD重新指向:

HEAD指向的版本就是當前版本,因此,Git允許我們在版本的歷史之間穿梭,使用命令git reset --hard commit_id

穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。

要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。

二、工作區和暫存區

Git和其他版本控制系統如SVN的一個不同之處就是有暫存區的概念。

git add 把文件添加到暫存區;git commit把暫存區的所有內容提交到當前分支。

關聯遠程倉庫:git remote add origin [email protected]:username/learngit.git  learngit遠程倉庫名稱

將本地庫內容推送到遠程庫上:git push -u origin master

由於遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以後的推送或者拉取時就可以簡化命令

要關聯一個遠程庫,使用命令git remote add origin git@server-name:path/repo-name.git

關聯後,使用命令git push -u origin master第一次推送master分支的所有內容;

此後,每次本地提交後,只要有必要,就可以使用命令git push origin master推送最新修改;

分佈式版本系統的最大好處之一是在本地工作完全不需要考慮遠程庫的存在,也就是有沒有聯網都可以正常工作,而SVN在沒有聯網的時候是拒絕幹活的!當有網絡的時候,再把本地提交推送一下就完成了同步,真是太方便了!

從遠程庫克隆:git clone

分支管理

你創建了一個屬於你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上幹活,想提交就提交,直到開發完畢後,再一次性合併到原來的分支上,這樣,既安全,又不影響別人工作。但Git的分支是與衆不同的,無論創建、切換和刪除分支,Git在1秒鐘之內就能完成!無論你的版本庫是1個文件還是1萬個文件。

HEAD嚴格來說不是指向提交,而是指向mastermaster纔是指向提交的,所以,HEAD指向的就是當前分支。

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

當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:你看,Git創建一個分支很快,因爲除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指針往前移動一步,而master指針不變

假如我們在dev上的工作完成了,就可以把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:所以Git合併分支也很快!就改改指針,工作區內容也不變!合併完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,我們就剩下了一條master分支:

創建並切換分支dev:git checkout -b dev  ==  git branch dev + git checkout dev       git  branch查看當前分支

git add + git commit -m ""後切換回master分支:git checkout master

把dev分支的工作成果合併到master分支上:git merge dev

git merge命令用於合併指定分支到當前分支

因爲創建、合併和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合併後再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全。

創建與合併分支

閱讀: 999261


版本回退裏,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向mastermaster纔是指向提交的,所以,HEAD指向的就是當前分支。

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

git-br-initial

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

 

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

git-br-create

你看,Git創建一個分支很快,因爲除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指針往前移動一步,而master指針不變:

git-br-dev-fd

假如我們在dev上的工作完成了,就可以把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:

git-br-ff-merge

所以Git合併分支也很快!就改改指針,工作區內容也不變!

合併完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,我們就剩下了一條master分支:

git-br-rm

真是太神奇了,你看得出來有些提交是通過分支完成的嗎?

 

下面開始實戰。

首先,我們創建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 b17d20e] branch test
 1 file changed, 1 insertion(+)

現在,dev分支的工作完成,我們就可以切換回master分支:

$ git checkout master
Switched to branch 'master'

切換回master分支後,再查看一個readme.txt文件,剛纔添加的內容不見了!因爲那個提交是在dev分支上,而master分支此刻的提交點並沒有變:

git-br-on-master

現在,我們把dev分支的工作成果合併到master分支上:

$ git merge dev
Updating d46f35e..b17d20e
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 b17d20e).

刪除後,查看branch,就只剩下master分支了:

$ git branch
* master

因爲創建、合併和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合併後再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全。

 

小結

Git鼓勵大量使用分支:

查看分支:git branch

創建分支:git branch <name>

切換分支:git checkout <name>

創建+切換分支:git checkout -b <name>

合併某分支到當前分支:git merge <name>

刪除分支:git branch -d <name>

在實際開發中,我們應該按照幾個基本原則進行分支管理:

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;

那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;

你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。

所以,團隊合作的分支看起來就像這樣:

準備合併dev分支,請注意--no-ff參數,表示禁用Fast forward

$ git merge --no-ff -m "merge with no-ff" dev

Bug分支:

場景:當前分支開發了一部分,不能提交,需要2個小時修改一個bug
git stash 暫存

1.切換master:git checkout master;2.新建bug分支並切換git checkout -b issue-101;3.修復bug提交,切換回master

,並完成合並:git merger --no-ff -m "merger bug fix 101" issue-101;4.切換回原來的開發分支dev:git stash list

查看,工作現場還在,Git把stash內容存在某個地方了,但是需要恢復一下,有兩個辦法:一是用git stash apply恢復,但是恢復後,stash內容並不刪除,需要用git stash drop來刪除;另一種方式是用git stash pop,恢復的同時把stash內容也刪除了

rebase:

這就是rebase操作的特點:把分叉的提交歷史“整理”成一條直線,看上去更直觀。缺點是本地的分叉提交已經被修改過了。

這種神奇的操作是怎麼實現的?其實原理非常簡單。我們注意觀察,發現Git把我們本地的提交“挪動”了位置,放到了f005ed4 (origin/master) set exit=1之後,這樣,整個提交歷史就成了一條直線。rebase操作前後,最終的提交內容是一致的,但是,我們本地的commit修改內容已經變化了,它們的修改不再基於d1be385 init hello,而是基於f005ed4 (origin/master) set exit=1,但最後的提交7e61ed4內容是一致的。

  • rebase操作可以把本地未push的分叉提交歷史整理成直線;

  • rebase的目的是使得我們在查看歷史提交的變化時更容易,因爲分叉的提交需要三方對比。

創建標籤:git tag <name>打了一個新標籤,用命令git tag查看所有標籤

默認標籤是打在最新提交的commit上的。有時候,如果忘了打標籤,比如,現在已經是週五了,但應該在週一打的標籤沒有打,怎麼辦?

方法是找到歷史提交的commit id,然後打上就可以了:git log     git tag v0.9 f52c633

注意,標籤不是按時間順序列出,而是按字母排序的。可以用git show <tagname>查看標籤信息:

還可以創建帶有說明的標籤,用-a指定標籤名,-m指定說明文字:

刪除標籤:git tag -d v0.1   推送到遠程:git push origin <tagname>    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章