Git&GitHub

廖雪峰教程

  • 0.使用GitHub
    0.1 添加到遠程庫
    0.2 從遠程庫克隆
    0.3 GitHub使用

  • 1.創建版本庫

  • 2.時光穿梭機
    2.1 版本回退
    2.2 工作區和暫存區
    2.3 管理修改
    2.4 撤銷修改
    2.5 刪除文件

  • 3.分支管理
    3.1 創建與合并分支
    3.2 解決沖突
    3.3 分支管理策略
    3.4 Bug分支
    3.5 Feature分支
    3.6 多人協作

  • 4.標簽管理
    4.1 創建標簽
    4.2 操作標簽

  • 5.自定義Git
    5.1 忽略特殊文件
    5.2 配置別名
    5.3 搭建Git服務器

  • 6.擴展
    6.1 rebase的使用

0.使用GitHub
生成SSH key,如果沒有key的話,在用戶主目錄下面,執行下面語句:

ssh-keygen -t rsa -C "youremail@example.com"

該語句在用戶主目錄下面生成.ssh文件夾,文件夾中有兩個文件,分別是id_rsa和id_rsa.pub,前者是私鎖,不能告訴別人,后者是公鎖,可以告訴別人,需要將后者即是id_rsa.pub中內容添加到GitHub的賬戶中,因為Git支持SSH協議,SSH key是GitHub用來識別代碼是該用戶提交過來的。

0.1 添加到遠程庫

git remote add origin https://github.com/Jayzen/demo_for_test.git 
#遠程庫的名字叫做origin,是默認的遠程庫的名稱,其中demo_for_test是用戶自定義的倉庫名稱
git push -u origin master
#第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令
git push origin master #第二次之后遠程庫的代碼提交(對比第一次提交少了-u 參數)

0.2 從遠程庫克隆

git clone https://github.com/Jayzen/gitskill.git #自己的電腦這個可行
git clone git@github.com:Jayzen/gitskill.git

0.3 GitHub使用
如果要修改一個開源庫,步驟如下:

fork   #fork一個項目,相當于在自己的github上面復制了一個相同的項目
git clone XX #在用戶的本地復制該代碼
git push  #用戶本地修改代碼之后,推送到GiHub中用戶本身的目錄下面
pull request #發起這個pull request,看作者是否接受

具體示意圖見如:

Paste_Image.png

1.創建版本庫

git init #初始化一個倉庫
git add <file> #添加到倉庫
git commit -m "some descriptions"  #提交到倉庫,其中后面顯示的-m是對本次提交的一次說明

2.時光穿梭機

git status #查看用戶的狀態
#如果只是對代碼進行了修改,之后沒有做任何改動,則會顯Changes not staged for commit
#如果是在當前文件夾內添加了一個文件,之后沒有做任何動作,則會顯示untracked files
#如果對文件進行了修改,執行了add,沒有執行commit,則會顯示Changes to be committed
#如果代碼全部提交到倉庫中,則會顯示nothing to commit, working directory clean
git diff #查看代碼做了哪些修改,這種狀態修改的說明只能是該文件沒有執行git add之前才能看到

2.1 版本回退

git log #顯示從近到遠的提交日志
git log --pretty=oneline #將這些日志按照行顯示
git reset --hard HEAD^ #將版本退回到上一次提交,其中HEAD^表示上一個版本,HEAD^^表示上上一個版本
git reset --hard commit_id #其中commit_id是commit過程中生成的id值
git reflog #記錄head指向的每一次命令

head指向append GPL


Paste_Image.png

改為head指向add distributed

Paste_Image.png

2.2 工作區和暫存區
工作區其實就是git當前工作的文件夾。

把文件往Git版本庫里添加的時候,是分兩步執行的:
第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。

Paste_Image.png

與此同時,在工作區中修改readme.txt文件和添加LICENSE,并且兩次使用add命令,結果如下所示:

Paste_Image.png

以上的結果可以看出,兩次add方法是將文件添加到暫存區中,執行git commit -m "fourth commit",得到以下的結果,暫存區是干凈的。

Paste_Image.png

2.3 管理修改
Git跟蹤的是修改,而不是文件。
git commit 提交給是是暫存區的內容,如果修改了文件,沒有執行commit add,那么git commit對修改的文件內容無效。

git diff HEAD -- readme.txt  #查看工作區和版本庫里面最新版本的區別

2.4 撤銷修改
第一種情況:在工作區中修改,當時沒有提交到暫存區

git checkout --file

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,這里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
第二種情況:已經提交到暫存區

git reset HEAD file  #可以把暫存區的修改撤銷掉,重新放回工作區
git checkout --file #重復第一種情況

其中

git reset  #命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。

2.5 刪除文件
當前工作區內有兩個文件,分別是demo.rb和test.rb,其中在工作區中刪除文件test.rb,則下面有兩種情況:

#第一種:確實要刪除該文件
git rm test.rb
git commit -m "remove test.rb"

自己測試了下,下面的代碼也可以實現刪除功能,因為版本控制跟蹤的修改,而不是文件。
git add .
git commit -m "remove test.rb"

#第二種:
刪除文件出現錯誤,因此相當于撤銷修改
git checkout --test.rb #git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。

3.1 創建和合并分支

git branch #查看分支
git branch <name> #創建分支
git checkout <name> #切換分支
git checkout -b <name> #創建+切換分支
git merge <name> #合并某分支到當前分支
git branch -d <name> #刪除分支

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點,每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長:

Paste_Image.png

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

Paste_Image.png

Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:

Paste_Image.png

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

Paste_Image.png

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

Paste_Image.png

3.2 解決沖突
當主分支和從分支在同一個地方進行修改了,并且進行合并之后,出現了沖突。

#生成另外一個分支,對這個分支進行修改,然后提交
git checkout -b feature
修改demo.rb中的內容
git add demo.rb
git commit -m "commit feature"

#回到master分支,對master分支進行修改,然后提交
git checkout master
修改demo.rb中的內容,并且和上一個部分修改同一個地方
git add demo.rb
git commit -m "commit master"

#對兩個分支進行合并
git merge feature #出現了conflict

#修改conflict的內容,重新進行提交
git add demo.rb
git commit -m "final commit"

#上面的內容對conflict內容進行了修改,并且在master分支上進行了合并成功

#刪除分支
git branch -d feature

#用圖像形式顯示合并
git log --graph --pretty=oneline --abbrev-commit

3.3 分支管理策略
每個人不應該在master分支上建立分支,而應該在dev分支上建立分支,每次提交應該針對dev分支,當發布版本時應該從dev分支上提交到master分支

如果按照上文的合并方式(fast forward)進行的話,如果刪除了分支,就會丟失分支信息,因此這里可以采用禁用Fast forward模式,Git就會在merge時生成一個新的commit。

git checkout -b dev
修改demo.rb文件內容
git add demo.rb
git commit -m "commit dev"

#切換到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev

#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit

下面圖片顯示分支信息:


Paste_Image.png

3.4 Bug分支
Bug分支的策略是把當前的分支存儲起來,然后建立bug分支,修復好之后再對當前分支進行恢復。

git status #當前分支下的內容
git stash #對當前分支進行存儲
git status #當對當前分支進行存儲之后,發現當前分支的status是空的

#對bug分支進行修復
git checkout master
git checkout -b bug-issue
對demo.rb文件內容進行修改
git add demo.rb
git commit -m "bug commit"
git checkout master 
git merge --no-ff -m "merge bug commit" bug-issue
git status  #查看工作目錄是空的

git slash list #查看slash
git slash apply #恢復后,stash內容并不刪除,你需要用git stash drop來刪除
git stash apply stash@{0} #恢復指定的slash
git slash pop #恢復的同時把stash內容也刪了
git slash list #恢復后查看slash的內容也沒有了

3.5 Feature分支
如果是開發新功能,最好是新建一個分支,如果這個分支已經被合并,那么刪除這個分支使用:

git branch -d feature

如果這個分支沒有被合并,刪除這個分支,需要用到下面的語句:

git branch -D feature

3.6 多人協作
從遠程克隆倉庫也是分多種情況,第一種情況是只有一個master分支的情況下:

git clone XX  #遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin
git remote #origin  此代碼是查看遠程庫的信息,遠程庫的默認信息是origin
git remote -v  #使用-v查看遠程庫更為詳細的信息
  origin git@github.com:michaelliao/learngit.git (fetch)
  origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev  #推送dev分支

第二種情況是當遠程庫存在多個分支時候,使用git clone語句克隆代碼,使用git branch語句只能查看master分支,為了顯示其他分支,需要創建遠程的origin的dev分支到本地:

git clone XX
git branch #master
#實際上被克隆的代碼庫有很多分支,而這里只能顯示master分支
git checkout -b dev origin/dev
#使用上面的語句在本地建立dev分支,和遠程庫的dev分支對象起來,同時獲得遠程庫的分支信息代碼
#在dev分支上修改代碼
git commit -m "add the dev" 
git push origin dev #將代碼推送到遠程庫dev分支中

第三情況是處理沖突:兩個人同時寫作同一個代碼庫,比如在feature分支上面,一個人已經作為修改,另外一個人在此人修改之前已經git clone到本地,并且在feature同一個地方做了修改,因此會出現conflict。

#已經有其他用戶在feature分支上面建立test.rb文件
#下面的代碼都是在本地的feature分支上進行
git add test.rb
git commit -m "add the test.rb"
git push origin feature

上面的代碼出現錯誤,根據提示可以知道,是因為出現了代碼沖突,根據提示使用git pull。

git pull #如果存在no tracking information,說明本地分支和遠程分支之間的鏈接關系沒有建立
git branch --set-upstream-to=origin/feature feature #設置feature和origin/feature的鏈接
git pull #出現沖突及沖突提示
#沖突解決好之后重新提交
git commit -m "conflict commit"
git push origin feature

4.標簽管理
標簽是版本庫的一個快照,若給版本庫打了一個標簽,就相當于在某個時候獲取一個特定時間的版本庫,標簽和分支不同,分支可以移動,標簽不能移動。
4.1 創建標簽

git checkout master #切換到最新的master分支上
git tag v1.0 #給最新的分支貼上標簽
git tag #查看所有標簽
默認情況下標簽是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的語句
git log --pretty=oneline --abbrev-commit  #顯示commit id log
git tag v0.9 1234234  #其中1234234是commit id值,即將標簽打在這個commit id中。
git show  v1.0 #查看某個版本的標簽
git tag -a v0.1 -m "version 0.1 released" 3628164
#創建帶有說明的標簽,用-a指定標簽名,-m指定說明文字

4.2 操作標簽

git tag -d v0.9  #刪除標簽
git push origin v0.9 #因為標簽都是在本地的,此代碼是推送標簽到遠程
git push origin --tags #一次性推送全部尚未推送到遠程的本地標簽

#如果標簽已經推送到遠程,要刪除遠程標簽就麻煩一點,先從本地刪除:
#然后,從遠程刪除。刪除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9

5.自定義Git

git config --global color.ui true #設置顏色

5.1 忽略特殊文件
在工作區建立 .gitignore
ruby的示例文件可以在這里找到

5.2 配置別名
配置別名就是在將Git的命令用其他名字來表示,示例代碼如下所示:

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。

每個倉庫的Git配置文件都放在.git/config文件中,其中別名就在[alias]后面,要刪除別名,直接把對應的行刪掉即可。

[core] 
  repositoryformatversion = 0 
  filemode = true bare = false 
  logallrefupdates = true 
  ignorecase = true 
  precomposeunicode = true
[remote "origin"]
  url = git@github.com:michaelliao/learngit.git 
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"] 
  remote = origin 
  merge = refs/heads/master
[alias] 
  last = log -1

而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig
中:

[alias] 
  co = checkout 
  ci = commit 
  br = branch 
  st = status
[user]
  name = Your Name 
  email = your@email.com

5.3 搭建Git服務器
見這里

6.擴展
6.1 rebase的使用
相關文檔
在master分支上簡歷mywork分支,示意圖如下所示:

Paste_Image.png

在mywork分支上提交兩次代碼,同時其他用戶在master分支上提交了兩次代碼,示意圖如下所示:

Paste_Image.png

在這里,你可以用"pull"命令把"origin"分支上的修改拉下來并且和你的修改合并; 結果看起來就像一個新的"合并的提交",示意圖如下所示:

Paste_Image.png

但是,如果你想讓"mywork"分支歷史看起來像沒有經過任何合并一樣,可以用git rebase,代碼如下所示:

git checkout mywork
git rebase origin

這些命令會把你的"mywork"分支里的每個提交(commit)取消掉,并且把它們臨時 保存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的這些補丁應用到"mywork"分支上。

Paste_Image.png

當'mywork'分支更新之后,它會指向這些新創建的提交(commit),而那些老的提交會被丟棄。 如果運行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會刪除。

Paste_Image.png

現在我們可以看一下用合并(merge)和用rebase所產生的歷史的區別:

Paste_Image.png

6.2 修改最近一次的提交 commit --amend
該功能會修改最近一次的提交,使用commit --amend
比如最開始是這樣的:

git log

需要對添加add的講解進行修改,使用下面代碼:

git add .
git commit --amend

上面的代碼會跳出一個編輯頁面,可以修改添加add的講解的值,修改為添加add和commit的講解,并且進行保存,使用git log操作,可以得到如下的結果:

git log

6.3 取消最新一次的提交 git revert head
下面的代碼可以取消最近一次的提交

git revert HEAD

原本最初的提交branch如下所示:

Paste_Image.png

執行git revert HEAD之后,變為如下的結果

Paste_Image.png

就是說針對“添加pull的講解”所變化的內容消失了。

6.4 使用reset來刪除前面的幾個提交
代碼如下所示:

git reset --hard HEAD~~ #這是刪除最前面的兩個提交
git reset --hard HEAD~ #這是刪除了最前面的一個提交
git reset --hard ORGI_HEAD #如果之前的reset出錯了,該代碼會返回最開始進行reset的位置

圖片演示如下:

before reset
after reset

6.5 **使用cherry-pick將其他分支中的內容添加到主分支中 **
如下圖所示:

Paste_Image.png

廖雪峰教程

  • 0.使用GitHub
    0.1 添加到遠程庫
    0.2 從遠程庫克隆
    0.3 GitHub使用

  • 1.創建版本庫

  • 2.時光穿梭機
    2.1 版本回退
    2.2 工作區和暫存區
    2.3 管理修改
    2.4 撤銷修改
    2.5 刪除文件

  • 3.分支管理
    3.1 創建與合并分支
    3.2 解決沖突
    3.3 分支管理策略
    3.4 Bug分支
    3.5 Feature分支
    3.6 多人協作

  • 4.標簽管理
    4.1 創建標簽
    4.2 操作標簽

  • 5.自定義Git
    5.1 忽略特殊文件
    5.2 配置別名
    5.3 搭建Git服務器

  • 6.擴展
    6.1 rebase的使用

0.使用GitHub
生成SSH key,如果沒有key的話,在用戶主目錄下面,執行下面語句:

ssh-keygen -t rsa -C "youremail@example.com"

該語句在用戶主目錄下面生成.ssh文件夾,文件夾中有兩個文件,分別是id_rsa和id_rsa.pub,前者是私鎖,不能告訴別人,后者是公鎖,可以告訴別人,需要將后者即是id_rsa.pub中內容添加到GitHub的賬戶中,因為Git支持SSH協議,SSH key是GitHub用來識別代碼是該用戶提交過來的。

0.1 添加到遠程庫

git remote add origin https://github.com/Jayzen/demo_for_test.git 
#遠程庫的名字叫做origin,是默認的遠程庫的名稱,其中demo_for_test是用戶自定義的倉庫名稱
git push -u origin master
#第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令
git push origin master #第二次之后遠程庫的代碼提交(對比第一次提交少了-u 參數)

0.2 從遠程庫克隆

git clone https://github.com/Jayzen/gitskill.git #自己的電腦這個可行
git clone git@github.com:Jayzen/gitskill.git

0.3 GitHub使用
如果要修改一個開源庫,步驟如下:

fork   #fork一個項目,相當于在自己的github上面復制了一個相同的項目
git clone XX #在用戶的本地復制該代碼
git push  #用戶本地修改代碼之后,推送到GiHub中用戶本身的目錄下面
pull request #發起這個pull request,看作者是否接受

具體示意圖見如:

Paste_Image.png

1.創建版本庫

git init #初始化一個倉庫
git add <file> #添加到倉庫
git commit -m "some descriptions"  #提交到倉庫,其中后面顯示的-m是對本次提交的一次說明

2.時光穿梭機

git status #查看用戶的狀態
#如果只是對代碼進行了修改,之后沒有做任何改動,則會顯Changes not staged for commit
#如果是在當前文件夾內添加了一個文件,之后沒有做任何動作,則會顯示untracked files
#如果對文件進行了修改,執行了add,沒有執行commit,則會顯示Changes to be committed
#如果代碼全部提交到倉庫中,則會顯示nothing to commit, working directory clean
git diff #查看代碼做了哪些修改,這種狀態修改的說明只能是該文件沒有執行git add之前才能看到

2.1 版本回退

git log #顯示從近到遠的提交日志
git log --pretty=oneline #將這些日志按照行顯示
git reset --hard HEAD^ #將版本退回到上一次提交,其中HEAD^表示上一個版本,HEAD^^表示上上一個版本
git reset --hard commit_id #其中commit_id是commit過程中生成的id值
git reflog #記錄head指向的每一次命令

head指向append GPL


Paste_Image.png

改為head指向add distributed

Paste_Image.png

2.2 工作區和暫存區
工作區其實就是git當前工作的文件夾。

把文件往Git版本庫里添加的時候,是分兩步執行的:
第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。

Paste_Image.png

與此同時,在工作區中修改readme.txt文件和添加LICENSE,并且兩次使用add命令,結果如下所示:

Paste_Image.png

以上的結果可以看出,兩次add方法是將文件添加到暫存區中,執行git commit -m "fourth commit",得到以下的結果,暫存區是干凈的。

Paste_Image.png

2.3 管理修改
Git跟蹤的是修改,而不是文件。
git commit 提交給是是暫存區的內容,如果修改了文件,沒有執行commit add,那么git commit對修改的文件內容無效。

git diff HEAD -- readme.txt  #查看工作區和版本庫里面最新版本的區別

2.4 撤銷修改
第一種情況:在工作區中修改,當時沒有提交到暫存區

git checkout --file

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,這里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
第二種情況:已經提交到暫存區

git reset HEAD file  #可以把暫存區的修改撤銷掉,重新放回工作區
git checkout --file #重復第一種情況

其中

git reset  #命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。

2.5 刪除文件
當前工作區內有兩個文件,分別是demo.rb和test.rb,其中在工作區中刪除文件test.rb,則下面有兩種情況:

#第一種:確實要刪除該文件
git rm test.rb
git commit -m "remove test.rb"

自己測試了下,下面的代碼也可以實現刪除功能,因為版本控制跟蹤的修改,而不是文件。
git add .
git commit -m "remove test.rb"

#第二種:
刪除文件出現錯誤,因此相當于撤銷修改
git checkout --test.rb #git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。

3.1 創建和合并分支

git branch #查看分支
git branch <name> #創建分支
git checkout <name> #切換分支
git checkout -b <name> #創建+切換分支
git merge <name> #合并某分支到當前分支
git branch -d <name> #刪除分支

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點,每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長:

Paste_Image.png

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

Paste_Image.png

Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:

Paste_Image.png

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

Paste_Image.png

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

Paste_Image.png

3.2 解決沖突
當主分支和從分支在同一個地方進行修改了,并且進行合并之后,出現了沖突。

#生成另外一個分支,對這個分支進行修改,然后提交
git checkout -b feature
修改demo.rb中的內容
git add demo.rb
git commit -m "commit feature"

#回到master分支,對master分支進行修改,然后提交
git checkout master
修改demo.rb中的內容,并且和上一個部分修改同一個地方
git add demo.rb
git commit -m "commit master"

#對兩個分支進行合并
git merge feature #出現了conflict

#修改conflict的內容,重新進行提交
git add demo.rb
git commit -m "final commit"

#上面的內容對conflict內容進行了修改,并且在master分支上進行了合并成功

#刪除分支
git branch -d feature

#用圖像形式顯示合并
git log --graph --pretty=oneline --abbrev-commit

3.3 分支管理策略
每個人不應該在master分支上建立分支,而應該在dev分支上建立分支,每次提交應該針對dev分支,當發布版本時應該從dev分支上提交到master分支

如果按照上文的合并方式(fast forward)進行的話,如果刪除了分支,就會丟失分支信息,因此這里可以采用禁用Fast forward模式,Git就會在merge時生成一個新的commit。

git checkout -b dev
修改demo.rb文件內容
git add demo.rb
git commit -m "commit dev"

#切換到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev

#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit

下面圖片顯示分支信息:


Paste_Image.png

3.4 Bug分支
Bug分支的策略是把當前的分支存儲起來,然后建立bug分支,修復好之后再對當前分支進行恢復。

git status #當前分支下的內容
git stash #對當前分支進行存儲
git status #當對當前分支進行存儲之后,發現當前分支的status是空的

#對bug分支進行修復
git checkout master
git checkout -b bug-issue
對demo.rb文件內容進行修改
git add demo.rb
git commit -m "bug commit"
git checkout master 
git merge --no-ff -m "merge bug commit" bug-issue
git status  #查看工作目錄是空的

git slash list #查看slash
git slash apply #恢復后,stash內容并不刪除,你需要用git stash drop來刪除
git stash apply stash@{0} #恢復指定的slash
git slash pop #恢復的同時把stash內容也刪了
git slash list #恢復后查看slash的內容也沒有了

3.5 Feature分支
如果是開發新功能,最好是新建一個分支,如果這個分支已經被合并,那么刪除這個分支使用:

git branch -d feature

如果這個分支沒有被合并,刪除這個分支,需要用到下面的語句:

git branch -D feature

3.6 多人協作
從遠程克隆倉庫也是分多種情況,第一種情況是只有一個master分支的情況下:

git clone XX  #遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin
git remote #origin  此代碼是查看遠程庫的信息,遠程庫的默認信息是origin
git remote -v  #使用-v查看遠程庫更為詳細的信息
  origin git@github.com:michaelliao/learngit.git (fetch)
  origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev  #推送dev分支

第二種情況是當遠程庫存在多個分支時候,使用git clone語句克隆代碼,使用git branch語句只能查看master分支,為了顯示其他分支,需要創建遠程的origin的dev分支到本地:

git clone XX
git branch #master
#實際上被克隆的代碼庫有很多分支,而這里只能顯示master分支
git checkout -b dev origin/dev
#使用上面的語句在本地建立dev分支,和遠程庫的dev分支對象起來,同時獲得遠程庫的分支信息代碼
#在dev分支上修改代碼
git commit -m "add the dev" 
git push origin dev #將代碼推送到遠程庫dev分支中

第三情況是處理沖突:兩個人同時寫作同一個代碼庫,比如在feature分支上面,一個人已經作為修改,另外一個人在此人修改之前已經git clone到本地,并且在feature同一個地方做了修改,因此會出現conflict。

#已經有其他用戶在feature分支上面建立test.rb文件
#下面的代碼都是在本地的feature分支上進行
git add test.rb
git commit -m "add the test.rb"
git push origin feature

上面的代碼出現錯誤,根據提示可以知道,是因為出現了代碼沖突,根據提示使用git pull。

git pull #如果存在no tracking information,說明本地分支和遠程分支之間的鏈接關系沒有建立
git branch --set-upstream-to=origin/feature feature #設置feature和origin/feature的鏈接
git pull #出現沖突及沖突提示
#沖突解決好之后重新提交
git commit -m "conflict commit"
git push origin feature

4.標簽管理
標簽是版本庫的一個快照,若給版本庫打了一個標簽,就相當于在某個時候獲取一個特定時間的版本庫,標簽和分支不同,分支可以移動,標簽不能移動。
4.1 創建標簽

git checkout master #切換到最新的master分支上
git tag v1.0 #給最新的分支貼上標簽
git tag #查看所有標簽
默認情況下標簽是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的語句
git log --pretty=oneline --abbrev-commit  #顯示commit id log
git tag v0.9 1234234  #其中1234234是commit id值,即將標簽打在這個commit id中。
git show  v1.0 #查看某個版本的標簽
git tag -a v0.1 -m "version 0.1 released" 3628164
#創建帶有說明的標簽,用-a指定標簽名,-m指定說明文字

4.2 操作標簽

git tag -d v0.9  #刪除標簽
git push origin v0.9 #因為標簽都是在本地的,此代碼是推送標簽到遠程
git push origin --tags #一次性推送全部尚未推送到遠程的本地標簽

#如果標簽已經推送到遠程,要刪除遠程標簽就麻煩一點,先從本地刪除:
#然后,從遠程刪除。刪除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9

5.自定義Git

git config --global color.ui true #設置顏色

5.1 忽略特殊文件
在工作區建立 .gitignore
ruby的示例文件可以在這里找到

5.2 配置別名
配置別名就是在將Git的命令用其他名字來表示,示例代碼如下所示:

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。

每個倉庫的Git配置文件都放在.git/config文件中,其中別名就在[alias]后面,要刪除別名,直接把對應的行刪掉即可。

[core] 
  repositoryformatversion = 0 
  filemode = true bare = false 
  logallrefupdates = true 
  ignorecase = true 
  precomposeunicode = true
[remote "origin"]
  url = git@github.com:michaelliao/learngit.git 
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"] 
  remote = origin 
  merge = refs/heads/master
[alias] 
  last = log -1

而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig
中:

[alias] 
  co = checkout 
  ci = commit 
  br = branch 
  st = status
[user]
  name = Your Name 
  email = your@email.com

5.3 搭建Git服務器
見這里

6.擴展
6.1 rebase的使用
相關文檔
在master分支上簡歷mywork分支,示意圖如下所示:

Paste_Image.png

在mywork分支上提交兩次代碼,同時其他用戶在master分支上提交了兩次代碼,示意圖如下所示:

Paste_Image.png

在這里,你可以用"pull"命令把"origin"分支上的修改拉下來并且和你的修改合并; 結果看起來就像一個新的"合并的提交",示意圖如下所示:

Paste_Image.png

但是,如果你想讓"mywork"分支歷史看起來像沒有經過任何合并一樣,可以用git rebase,代碼如下所示:

git checkout mywork
git rebase origin

這些命令會把你的"mywork"分支里的每個提交(commit)取消掉,并且把它們臨時 保存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的這些補丁應用到"mywork"分支上。

Paste_Image.png

當'mywork'分支更新之后,它會指向這些新創建的提交(commit),而那些老的提交會被丟棄。 如果運行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會刪除。

Paste_Image.png

現在我們可以看一下用合并(merge)和用rebase所產生的歷史的區別:

Paste_Image.png

6.2 修改最近一次的提交 commit --amend
該功能會修改最近一次的提交,使用commit --amend
比如最開始是這樣的:

git log

需要對添加add的講解進行修改,使用下面代碼:

git add .
git commit --amend

上面的代碼會跳出一個編輯頁面,可以修改添加add的講解的值,修改為添加add和commit的講解,并且進行保存,使用git log操作,可以得到如下的結果:

git log

6.3 取消最新一次的提交 git revert head
下面的代碼可以取消最近一次的提交

git revert HEAD

原本最初的提交branch如下所示:

Paste_Image.png

執行git revert HEAD之后,變為如下的結果

Paste_Image.png

就是說針對“添加pull的講解”所變化的內容消失了。

6.4 使用reset來刪除前面的幾個提交
代碼如下所示:

git reset --hard HEAD~~ #這是刪除最前面的兩個提交
git reset --hard HEAD~ #這是刪除了最前面的一個提交
git reset --hard ORGI_HEAD #如果之前的reset出錯了,該代碼會返回最開始進行reset的位置

圖片演示如下:

before reset
after reset

6.5 **使用cherry-pick將其他分支中的內容添加到主分支中 **
如下圖所示:

Paste_Image.png

添加commit的講解添加到master分支中,代碼如下所示:

git checkout master 
git cherry-pick 99daed2

#下面的提示代碼是正常現象,說明提交成功
error: could not apply 99daed2... commit
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

#但是如果出現沖突的話,需要添加如下的進行如下的操作
git add filename
git commit 

6.6 **使用rebase -i 匯合提交 **
這是做的事情是講master上面最近的兩次進行合并,匯合為一次提交,使用的代碼如下:

git rebase -i HEAD~~

#上面的代碼執行之后,會有下面的代碼界面出現,將第二行的pick改為squash

pick 9a54fd4 添加commit的說明
pick 0d4a808 添加pull的說明

# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.


#編輯保存退出,然后出現了編輯界面,編輯里面的值,該值將成為合并commit的說明

示意圖如下所示:

Paste_Image.png

就是將添加commit的講解添加pull的講解進行合并,成為一個commit。示意圖如下所示:

Paste_Image.png

6.7 用rebase -i 修改提交
在這里修改添加commit的講解

Paste_Image.png

代碼修改如下所示:

git rebase -i HEAD~~

將第一行的pick改為eidt,保存之后退出
pick 9a54fd4 添加commit的說明
pick 0d4a808 添加pull的說明

# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

#打開sample.txt,適當地修改“commit的講解”部分
git add sample.txt
git commit --amend

#已經commit,但是rebase操作還沒結束。若要通知這個提交的操作已經結束,請指定 --continue選項執行rebase。
git rebase --continue

6.8 把分支內容合并成一個提交,并導入到master分支
示意圖如下所示:

Paste_Image.png

把下面的一個分支合并成一個提交,并導入的master分支中,具體的代碼如下所示:

git checkout master
git merge --squash issue1
#出現了下面的提示,說明提交成功
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
#出現下面的提示,則說明提交失敗,出現了沖突
Auto-merging sample.txt
CONFLICT (content): Merge conflict in sample.txt
Squash commit -- not updating HEAD
Automatic merge failed; 
fix conflicts and then commit the result.

#說明發生了沖突,修改之后進行提交
git add sample.txt
git commit

6.9使用二分法查找bug
二分法的原理
代碼演示如下:

git bisect start master commit_id #master是bad點,commit_id是最開始提交點
git bisect run make test  #進行了自動化測試,此代碼可以測試出錯誤點
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容