Git基本使用

1、Git介紹

集中式和分佈式的區別:

集中式
Git基本使用
  版本庫是集中存放在中央服務器的,而幹活的時候,用的都是本身的電腦,因此要先從中央服務器取得最新的版本,而後開始幹活,幹完活了,再把本身的活推送給中央服務器。集中式的缺點就是:工做必須在同一網絡下,傳輸速率慢,並且一旦中央服務器宕機,全部人不能工做。
分佈式
Git基本使用
  布式版本控制特色是:每一個人的電腦上都是一個完整的版本庫,這樣,你工做的時候,就不須要聯網了,由於版本庫就在你本身的電腦上。若是某一我的的電腦壞掉了沒關係,隨便從其餘人那裏複製一個就能夠了。分佈式版本控制系統一般也有一臺充當「中央服務器」的電腦,但這個服務器的做用僅僅是用來方便「交換」你們的修改,沒有它你們也同樣幹活,只是交換修改不方便而已。git

2、Git的基礎部分

Git的版本庫

  版本庫又名倉庫,英文名repository,你能夠簡單理解成一個目錄,這個目錄裏面的全部文件均可以被Git管理起來,每一個文件的修改、刪除,Git都能跟蹤,以便任什麼時候刻均可以追蹤歷史,或者在未來某個時刻能夠「還原」。
建立版本庫github

#找一個空目錄,做爲工做空間
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master)
$ pwd
/e/code_test/git_test
#建立一個目錄
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master)
$ mkdir learngit
#進入目錄
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test (master)
$ cd learngit/
#將此目錄初始化爲倉庫
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git init
Initialized empty Git repository in E:/code_test/git_test/learngit/.git/

此時就會看見該目錄下:
Git基本使用shell

說明倉庫初始化成功!!!

實戰操做
需求:編寫一個文件,將其放入git倉庫管理。vim

#編寫一個文件:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt
加入:
Git is a version control system.
Git is free software.
#告訴git,把文件添加到倉庫
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git add readme.txt
#告訴git,把文件提交到倉庫
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git commit -m "wrote a readme file"

#查看此時工做空間的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean  #出現這句話表示工做空間很乾淨,最好的狀態。

補充:這裏先add而後在commit的意義是,由於commit能夠一次提交不少文件,因此你能夠屢次add不一樣的文件。

3、關於git的版本回退、修改、撤銷、刪除操做

add和commit以後的狀態介紹

#第一步,修改倉庫中的一個文件
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt
添加一行:
Git is good software.
#第二步,查看此時的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
注意打印的內容: 
On branch master   #在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   #具體被modify的文件

no changes added to commit (use "git add" and/or "git commit -a")

#查看哪裏被修改了
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..f2cbe56 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@   #表示新添加了一行
 Git is a version control system.
 Git is free software.
+Git is good software.   #這一行是新添加的。

#此時咱們在提交
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git add readme.txt

#查看此時的工做空間的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
Changes to be committed:  #提示 ,此時須要提交
  (use "git reset HEAD <file>..." to unstage)
        modified:   readme.txt

#最終咱們把修改的提交
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git commit -m "change one line on readme.txt"

#查看此時的工做空間的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean #表示提交成功,此時的工做空間很乾淨!!

版本的回退

 在倉庫中的內容通過屢次修改以後,咱們也不知道每個版本具體修改了什麼內容,此時可使用git log顯示從最近到最遠的提交日誌,咱們能夠看到2次提交,最近的一次是change one line on readme.txt,最先的一次是wrote a readme file。
Git基本使用
也可使用:git log - -pretty=oneline 輸出少許的信息。
Git基本使用
 標紅框的表示的是,此時修改的版本號。
 通過上面的鋪墊,咱們學習一下,若是進行版本的回退:
 首先,Git必須知道當前版本是哪一個版本,在Git中,用HEAD表示當前版本,也就是最新的提交1094adb...(注意個人提交ID和你的確定不同),上一個版本就是HEAD^,上上一個版本就是HEAD^^,固然往上100個版本寫100個^比較容易數不過來,因此寫成HEAD~100。服務器

#退回到上一個版本
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git reset --hard HEAD^
HEAD is now at b2d3770 wrote a readme file

#使用git log查看一下日誌
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git log

Git基本使用
最近一次的change one line on readme.txt已經不存在了!網絡

#如今又想回到當初的版本,怎麼辦?
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git reset --hard 93fc40   #最後一個參數,是須要回到的版本的版本號(不用全寫)
HEAD is now at 93fc40d change one line on readme.txt

#此時再次查看git log
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git log

Git基本使用
OK,又回來了!app

#可是若是不知道版本號,怎麼辦?
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git reflog
93fc40d (HEAD -> master) HEAD@{0}: reset: moving to 93fc40
b2d3770 HEAD@{1}: reset: moving to HEAD^
93fc40d (HEAD -> master) HEAD@{2}: commit: change one line on readme.txt
b2d3770 HEAD@{3}: commit (initial): wrote a readme file
你會發現的你的操做動做,都被記錄下來了,此時再去其中尋找版本號便可。

這種版本的來回切換,到底原理是什麼呢?
Git基本使用
Git的版本回退速度很是快,由於Git在內部有個指向當前版本的HEAD指針,當你回退版本的時候,Git僅僅是把HEAD指向change one line on readme.txt。
HEAD指向改成那個版本,當前版本就是哪個。
Git基本使用ssh

工做區和暫存區的介紹

工做區:電腦裏能看到的目錄。
版本庫:工做區有一個隱藏目錄.git,這個目錄就是是Git的版本庫。
Git的版本庫裏存了不少東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲咱們自動建立的第一個分支master,以及指向master的一個指針叫HEAD。
Git基本使用
以前講了咱們把文件往Git版本庫裏添加的時候,是分兩步執行的:分佈式

  • 第一步是用「git add」把文件添加進去,實際上就是把文件修改添加到暫存區
  • 第二步是用「git commit」提交更改,實際上就是把暫存區的全部內容提交到當前分支。
    接下來咱們使用圖的方式,舉一個例子,深刻了解一下這幾個概念:
    版本庫的開始狀態
    Git基本使用
    此時在版本庫中add兩個文件:hive.txt、hadoop.txt,此時版本庫的狀態
    Git基本使用
    此時執行一次commit ,此時版本庫的狀態
    Git基本使用

管理修改

#修改工做區的中一個文件
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt
#而後添加的暫存區
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git add readme.txt
#再次修改文件
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt

#提交
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git commit -m "two times changes"

#查看此時的倉庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ 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 add -> 第二次修改 -> git commit,Git管理的是修改,當你用git add命令後,在工做區的第一次修改被放入暫存區,準備提交,可是,在工做區的第二次修改並無放入暫存區,因此,git commit只負責把暫存區的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。

此時查看工做區和版本庫裏面最新版本的區別:
$ git diff HEAD -- readme.txt

Git基本使用
果真不一樣的地,就在第二次的修改。
若是咱們:第一次修改 -> git add -> 第二次修改 -> git add -> git commit
而後,版本庫中最新的版本就和當前工做空間中的一致了。ide

撤銷修改

狀況一:對文件作了修改,可是沒有add到暫存區。

#第一步:對文件作了不正確的修改
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt

#第二步查看倉庫版本庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ 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 checkout -- readme.txt所有撤銷在工做區的修改
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -- readme.txt
再次查看文件,以前的修改被撤銷。

#查看此時的版本庫的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean

狀況二:對文件作了錯誤的修改,而且已經add到暫存區中

#第一步:對文件作了不正確的修改
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt

#二:添加到暫存區
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git add readme.txt

#查看狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   readme.txt

#用命令git reset HEAD <file>能夠把暫存區的修改撤銷掉(unstage)
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git reset HEAD readme.txt

#再次查看版本庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ 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")

#最後再次撤銷工做區的修改便可
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -- readme.txt

#查看此時的版本庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean

刪除文件

在Git中,刪除也是一個修改操做。

#在工做空間中刪除一個文件:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ rm -rf test.txt

#查看版本庫的狀態
$ 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:    test.txt
no changes added to commit (use "git add" and/or "git commit -a")
此時git知道你在刪除一個文件,此時版本庫和工做空間中的文件不一致了。
#從版本庫中將文件刪除,保證版本庫和工做空間中一致
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git rm test.txt

#再次查看版本庫中的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        deleted:    test.txt

#最終提交一下這次的刪除操做
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git commit -m "remove test.txt"

#再次查看版本庫中的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean

4、git的高級操做之分支管理

分支管理的介紹

 在版本回退裏,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。
 一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:
Git基本使用
每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長:
Git基本使用
當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
Git基本使用
Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!
不過,從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:
Git基本使用
假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:
Git基本使用
合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:
Git基本使用

建立和合並分支實戰

#建立dev分支,而後切換到dev分支:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -b dev
Switched to a new branch 'dev'

#查看當前分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git branch
* dev
  Master

#在Dev分支上,修改文件
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ vim readme.txt

#添加到暫存區並提交
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git add readme.txt
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git commit -m "dev branch test"
[dev 1d10b07] dev branch test
 1 file changed, 1 insertion(+)

#此時切換到master分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git checkout master
Switched to branch 'master'
此時查看剛剛修改的內容,發現不見了,在mater分支上並無修改過。

#把dev分支的工做成果合併到master分支上:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git merge dev
Updating 8c466d3..1d10b07
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
注意:上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。

#合併後,將Dev這個分支刪除
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git branch -d dev
Deleted branch dev (was 1d10b07).
#查看此時的分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git branch
* master    #只有一個master,Dev被刪除

解決衝突

衝突的由來
在master分支上新建一個update分支:
Git基本使用
而後在update上進行了add和commit:
Git基本使用
而後切換到master分支,而且進行了add和commit:
Git基本使用
此時兩個分支上的都作了修改和提交,而且修改的內容不同,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突。
命令實戰

#建立並切換到一個分支上
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -b update
Switched to a new branch 'update'
#修改文件、add和commit
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update)
$ vim readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update)
$ git add readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update)
$ git commit -m "change woman"
[update 01c7377] change woman
 1 file changed, 1 insertion(+), 1 deletion(-)

#切換到master分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (update)
$ git checkout master
Switched to branch 'master'

#修改、add和commit
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ vim readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git add readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git commit -m "change mans"
[master 0ed89f1] change mans'
 1 file changed, 1 insertion(+), 1 deletion(-)

#分支合併
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git merge update
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

#查看此時的倉庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master|MERGING)
$ git status
On branch master
You have unmerged paths.    #合併出現問題
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)
Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   readme.txt
no changes added to commit (use "git add" and/or "git commit -a")

#查看文件,手動解決衝突

Git基本使用

#再次提交
$ git add readme.txt
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master|MERGING)
$ git commit -m "conflict fixed"
[master 2455cde] conflict fixed

#查看狀態(衝突解決)
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git status    
On branch master
nothing to commit, working tree clean

#用帶參數的git log也能夠看到分支的合併狀況:
$ git log --graph --pretty=oneline --abbrev-commit
*   2455cde (HEAD -> master) conflict fixed
|\
| * 01c7377 (update) change woman
* | 0ed89f1 change mans'
|/
* 1d10b07 dev branch test
* 8c466d3 remove test.txt
* b4924af add file test.txt
* c204725 second time change
* bb14dd9 two times changes
* 93fc40d change one line on readme.txt
* b2d3770 wrote a readme file
上面的log可能不容易懂,如今給他換成圖形

Git基本使用

分支管理策略

一般,合併分支時,若是可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。若是要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就能夠看出分支信息。使用--no-ff方式的git merge就會強制禁止Fast forward模式。

#建立並切換到分支
dministrator@WIN10-901241016 MINGW64 /e/code_test/git_te      st/learngit (master)
$ git checkout -b dev
Switched to a new branch 'dev'

#修改文件,並add和commit
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ vi readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git add readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git commit -m "add one line in readme.txt"
[dev 47cf755] add one line in readme.txt
 1 file changed, 1 insertion(+)

#切換到master
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git checkout master
Switched to branch 'master'

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git branch
  dev
* master

#準備合併dev分支,請注意--no-ff參數,表示禁用Fast forward:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
注意:本次合併建立了一個新的commit,因此加上-m參數,把commit描述寫進去。

#查看歷史分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git log --graph --pretty=oneline --abbrev-commit

Git基本使用
最終不使用Fast forward模式,merge後就像這樣:
Git基本使用

bug分支

  軟件開發中,bug就像屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此,每一個bug均可以經過一個新的臨時分支來修復,修復後,合併分支,而後將臨時分支刪除。
  需求:接到一個修復一個代號101的bug的任務時,很天然地,你想建立一個分支issue-101來修復它,可是,等等,當前正在dev上進行的工做尚未提交,並非你不想提交,而是工做只進行到一半,還無法提交,預計完成還需1天時間。可是,必須在兩個小時內修復該bug,怎麼辦?

#建立並切換到一個分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -b dev
Switched to a new branch 'dev'

#在dev分支上進行工做
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ vim readme.txt

#此時須要切換到master上,並修改內容,可是此時查看狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git status
On branch dev
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還提供了一個stash功能,能夠把當前工做現場「儲藏」起來,等之後恢復現場後繼續工做:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git stash
Saved working directory and index state WIP on dev: 2752807 merge with no-ff

#查看版本庫狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git status
On branch dev
nothing to commit, working tree clean
工做空間被保存,此時能夠切換至master,修改bug。

#切換至master,並建立臨時的分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git checkout master
Switched to branch 'master'

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout -b issue-101
Switched to a new branch 'issue-101'

#修改bug,並add和commit
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101)
$ vim readme.txt
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101)
$ git add readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101)
$ git commit -m "bug already update"
[issue-101 5964260] bug already update
 1 file changed, 1 insertion(+), 1 deletion(-)

#切換到master分支,並完成合並,最後刪除issue-101分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (issue-101)
$ git checkout master
Switched to branch 'master'

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ 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(-)

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git branch -d issue-101
Deleted branch issue-101 (was 5964260).

#修復bug以後,回到工做區繼續幹活
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (master)
$ git checkout dev
Switched to branch 'dev'

#查看此時的工做區狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git status
On branch dev  
nothing to commit, working tree clean   #很乾淨

#用git stash list命令看看,剛纔的工做現場存到哪去了?
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git stash list
stash@{0}: WIP on dev: 2752807 merge with no-ff

#回覆工做現場,通常有兩個方法:
一是用git stash apply恢復,可是恢復後,stash內容並不刪除,你須要用git stash drop來刪除;
另外一種方式是用git stash pop,恢復的同時把stash內容也刪了:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git stash pop

#查看此時的工做空間的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git status
On branch dev
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")
此時回到了剛剛工做是的狀態!!!

補充
若是想屢次使用stash,先用git stash list查看,而後恢復指定的stash,用命令:
#git stash apply stash@{0}

Feature分支

  軟件開發中,總有無窮無盡的新的功能要不斷添加進來。添加一個新功能時,你確定不但願由於一些實驗性質的代碼,把主分支搞亂了,因此,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
  需求:開始須要新開發一個功能,此時創建一個新的分支進行開發,開發完成以後add和commit,而後進入dev分支,進行分支的合併,可是此時的這個任務取消,須要刪除這個分支,可是Git提示,新建的分支沒有被合併不能刪除,若是刪除,將丟失掉修改,若是要強行刪除,須要使用大寫的-D參數。

#建立分支,並修改內容,add和commit
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git checkout -b new-option
Switched to a new branch 'new-option'
M       readme.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option)
$ vim feature

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option)
$ git add feature
warning: LF will be replaced by CRLF in feature.
The file will have its original line endings in your working directory.

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option)
$ git commit -m " add feature"
[new-option f0e5187]  add feature
 1 file changed, 1 insertion(+)
 create mode 100644 feature

#切換到dev
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (new-option)
$ git checkout dev
Switched to branch 'dev'
M       readme.txt

#強行刪除剛剛編輯的分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git branch -D new-option
Deleted branch new-option (was f0e5187).

#查看此時的工做空間的狀態
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git status
On branch dev
nothing to commit, working tree clean

5、git的高級操做之標籤操做

git的標籤介紹

  發佈一個版本時,咱們一般先在版本庫中打一個標籤(tag),這樣,就惟一肯定了打標籤時刻的版本。未來不管何時,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。因此,標籤也是版本庫的一個快照。
  Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指針,因此,建立和刪除標籤都是瞬間完成的。
  雖然每次的commit都有一個commit號,可是這個號是隨機生成的,不是很好找。使用標籤的話就很容易找出相應的版本,而後會很快的找出對應的版本。

建立標籤

#切換到須要打標籤的分支上:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git branch
* dev
  master

#敲命令git tag <name>就能夠打一個新標籤:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag v1.0

#查看標籤
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag
v1.0
注意:默認標籤是打在最新提交的commit上的。
#有時候,若是忘了打標籤,好比昨天的標籤忘記打嗎該怎麼辦?
#找到歷史提交的commit id:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git log --pretty=oneline --abbrev-commit
15d01da (HEAD -> dev) add shell script
300b129 add test.txt
993ddf5 (tag: v1.0, master) Initial commit

#對300b129 add test.txt打標籤
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag v0.9 300b129

#查看標籤
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag
v0.9
v1.0
注意:標籤不是按時間順序列出,而是按字母排序的。

#用git show <tagname>查看標籤信息:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git show v0.9
commit 300b1296640faab2ad0efddae2bd24fa11993d4c (tag: v0.9)
Author: zy <m18726234267@163.com>
Date:   Wed Mar 6 10:00:44 2019 +0800

    add test.txt

diff --git a/test.txt b/test.txt
new file mode 100644
index 0000000..8d3e51d
--- /dev/null
+++ b/test.txt
@@ -0,0 +1 @@
+this is a test text.

#固然咱們在建立標籤的時候,用-a指定標籤名,-m指定說明文字:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag -a v0.1 -m "add shell script" 15d01da

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git show v0.1

Git基本使用

操做標籤

#標籤的刪除
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag -d v0.1
Deleted tag 'v0.1' (was e176957)

#推送某個標籤到遠程,使用命令git push origin <tagname>:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git push origin v1.0

#一次性推送所有還沒有推送到遠程的本地標籤:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git push origin --tags

#刪除遠程的標籤(先刪除本地,再刪除遠程):
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git tag -d v0.9

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_mayun (dev)
$ git push origin :refs/tags/v0.9

6、遠程倉庫

添加遠程庫

已經在本地建立了一個Git倉庫後,又想在GitHub建立一個Git倉庫,而且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既能夠做爲備份,又可讓其餘人經過該倉庫來協做,真是一舉多得。

  • 首先:登錄GitHub,而後,在右上角找到「Create a new repo」按鈕,建立一個新的倉庫:
    Git基本使用
  • 在Repository name填入遠程「倉庫名稱」,其餘保持默認設置,點擊「Create repository」按鈕,就成功地建立了一個新的Git倉庫:
    Git基本使用
  • 而後根據gitHub的提示一步一步操做:
    Git基本使用
    此時在gitHub的倉庫中就出現了本地倉庫的文件:
    Git基本使用
    補充
    #表示的是鏈接gitHub上的遠程倉庫
    $ git remote add origin git@github.com:michaelliao/learngit.git
    #把本地庫的全部內容推送到遠程庫上
    $ git push -u origin master

    用git push命令,其實是把當前分支master推送到遠程。因爲遠程庫是空的,咱們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在之後的推送或者拉取時就能夠簡化命令。當一次推送成功以後:只要本地做了提交,就能夠經過命令:

    git push origin master

    從遠程庫中克隆

    #此時咱們在遠程倉庫中有相應的數據,咱們想下載到本地倉庫:
    $ git clone git@github.com:ZZY478086819/test_repositort.git

    這樣在本地的目錄中就要從遠程倉庫中克隆的文件。
    注意:Git支持多種協議,包括https,但經過ssh支持的原生git協議速度最快。

    多人協做

      當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。

#要查看遠程庫的信息,用git remote:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git remote
origin
#用git remote -v顯示更詳細的信息:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git remote -v
origin  git@github.com:ZZY478086819/test_repositort.git (fetch)
origin  git@github.com:ZZY478086819/test_repositort.git (push)
#推送分支,就是把該分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_test/learngit (dev)
$ git push origin master(分支名,固然也能夠推送其餘的分支)

注意
• master分支是主分支,所以要時刻與遠程同步;
• dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
• bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
• feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。

抓取分支

  多人協做時,你們都會往master和dev分支上推送各自的修改,如今,模擬一個你的小夥伴,能夠在另外一臺電腦或者同一臺電腦的另外一個目錄下克隆。

#從遠端克隆
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test
$ git clone git@github.com:ZZY478086819/test_repositort.git

#查看本地分支,可是隻能看見master分支
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (master)
$ git branch
* master

#如今要在dev分支上開發,就必須建立遠程origin的dev分支到本地,因而建立本地dev分支:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (master)
$ git checkout -b dev origin/dev

#在dev上繼續修改,而後,時不時地把dev分支push到遠程:
Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev)
$ vim env.txt

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev)
$ git add env.txt
warning: LF will be replaced by CRLF in env.txt.
The file will have its original line endings in your working directory.

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev)
$ git commit -m "add env"

Administrator@WIN10-901241016 MINGW64 /e/code_test/git_origin_test/test_repositort (dev)
$ git push origin dev
#你的小夥伴已經向origin/dev分支推送了他的提交,而碰巧你也對一樣的文件做了修改,並試圖推送
$ cat env.txt
env

$ git add env.txt

$ git commit -m "add new env"
[dev 7bd91f1] add new env
 1 file changed, 1 insertion(+)
 create mode 100644 env.txt

$ git push origin dev
To github.com:michaelliao/learngit.git
 ! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:ZZY478086819/test_repositort.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

推送失敗,由於你的小夥伴的最新提交和你試圖推送的提交有衝突,解決辦法也很簡單,Git已經提示咱們,先用git pull把最新的提交從origin/dev抓下來,而後,在本地合併,解決衝突,再推送:

$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> dev

git pull也失敗了,緣由是沒有指定本地dev分支與遠程origin/dev分支的連接,根據提示,設置dev和origin/dev的連接:
#git branch --set-upstream-to=origin/dev dev
再pull:
#git pull
這回git pull成功,可是合併有衝突,須要手動解決,解決的方法和分支管理中的解決衝突徹底同樣。解決後,提交,再push:

#解決衝突以後提交,並push
$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict

$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:ZZY478086819/test_repositort.git
   7a5e5dd..57c53ab  dev -> dev

總結:這裏出現衝突的緣由是,當你的同事修改代碼以後,進行push,此時dev分支已經被修改,可是你沒有獲得最新的修改後的dev分支的代碼,此時你的本地的版本庫中的最新的代碼和遠程倉庫中的不一致,致使了這次push失敗,因此你須要手動的將遠端的dev分支代碼pull下來,進行衝突解決,才能push。

相關文章
相關標籤/搜索