1. 程式人生 > >git的分支,多人協作,標簽管理

git的分支,多人協作,標簽管理

效果 命令 app result detail http 數據 owin rewind

一.分支

1.分支的簡介

  在進行提交操作時,Git 會保存一個提交對象(commit object),

2.分支的創建

  創建一個 testing 分支, 你需要使用 git branch 命令:

$ git branch testing

3.分支的切換

$ git checkout testing

  再提交一次:

$ vim test.rb
$ git commit -a -m made a change

  首先,我們創建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命令會列出所有分支,當前分支前面會標一個*號。

  對readme.txt做個修改,加上一行:

Creating a new branch is quick.

4.分支的刪除

  使用帶 -d選項的 git branch

命令來刪除分支:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

5.分支的合並

  檢出到你想合並入的分支,然後運行 git merge 命令:

$ git checkout master
Switched to branch master
$ git merge iss53
Merge made by the recursive strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

遇到沖突時的分支合並 

  有時候合並操作不會如此順利。 如果你在兩個不同的分支中,對同一個文件的同一個部分進行了不同的修改,Git 就沒法幹凈的合並它們。 如果你對 #53 問題的修改和有關 hotfix

的修改都涉及到同一個文件的同一處,在合並它們的時候就會產生合並沖突:

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

  此時 Git 做了合並,但是沒有自動地創建一個新的合並提交。 Git 會暫停下來,等待你去解決合並產生的沖突。 你可以在合並沖突後的任意時刻使用 git status 命令來查看那些因包含合並沖突而處於未合並(unmerged)狀態的文件:

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      index.html

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

  任何因包含合並沖突而有待解決的文件,都會以未合並狀態標識出來。 Git 會在有沖突的文件中加入標準的沖突解決標記,這樣你可以打開這些包含沖突的文件然後手動解決沖突。 出現沖突的文件會包含一些特殊區段,看起來像下面這個樣子:

<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
 please contact us at [email protected]
</div>
>>>>>>> iss53:index.html

  這表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因為你在運行 merge 命令的時候已經檢出到了這個分支)在這個區段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 為了解決沖突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也可以自行合並這些內容。 例如,你可以通過把這段內容換成下面的樣子來解決沖突:

<div id="footer">
please contact us at [email protected]
</div>

  上述的沖突解決方案僅保留了其中一個分支的修改,並且 &lt;&lt;&lt;&lt;&lt;&lt;&lt; , ======= , 和 &gt;&gt;&gt;&gt;&gt;&gt;&gt; 這些行被完全刪除了。 在你解決了所有文件裏的沖突之後,對每個文件使用 git add 命令來將其標記為沖突已解決。 一旦暫存這些原本有沖突的文件,Git 就會將它們標記為沖突已解決。

6.分支管理

$ git branch
  iss53
* master
  testing

  master 分支前的 * 字符:它代表現在檢出的那一個分支

Bug分支

  有了bug就需要修復,在Git中,由於分支是如此的強大,所以,每個bug都可以通過一個新的臨時分支來修復,修復後,合並分支,然後將臨時分支刪除。

  Git還提供了一個stash功能,可以把當前工作現場“儲藏”起來,等以後恢復現場後繼續工作:

$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge

  首先確定要在哪個分支上修復bug,假定需要在master分支上修復,就從master創建臨時分支:

$ git checkout master
Switched to branch master
Your branch is ahead of origin/master by 6 commits.
  (use "git push" to publish your local commits)

$ git checkout -b issue-101
Switched to a new branch ‘issue-101‘

  現在修復bug,需要把“Git is free software ...”改為“Git is a free software ...”,然後提交:

$ git add readme.txt 
$ git commit -m "fix bug 101"
[issue-101 4c805e2] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)

  修復完成後,切換到master分支,並完成合並,最後刪除issue-101分支:

$ git checkout master
Switched to branch master
Your branch is ahead of origin/master by 6 commits.
  (use "git push" to publish your local commits)

$ 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(-)

  現在,是時候接著回到dev分支

$ git checkout dev
Switched to branch dev

$ git status
On branch dev
nothing to commit, working tree clean

  工作區是幹凈的,剛才的工作現場存到哪去了?用git stash list命令看看:

$ git stash list
stash@{0}: WIP on dev: f52c633 add merge

  工作現場還在,Git把stash內容存在某個地方了,但是需要恢復一下,有兩個辦法:

一是用git stash apply恢復,但是恢復後,stash內容並不刪除,你需要用git stash drop來刪除;

  另一種方式是用git stash pop,恢復的同時把stash內容也刪了:

$ git stash pop
On branch dev
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   hello.py

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

Dropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)

  再用git stash list查看,就看不到任何stash內容了:

$ git stash list

  你可以多次stash,恢復的時候,先用git stash list查看,然後恢復指定的stash,用命令:

$ git stash apply stash@{0}

7.dev 分支

  準備開發:

$ git checkout -b dev-vulcan
Switched to a new branch dev-vulcan

  5分鐘後,開發完畢:

$ git add vulcan.py

$ git status
On branch dev-vulcan
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   vulcan.py

$ git commit -m "add feature vulcan"
[feature-vulcan 287773e] add feature vulcan
 1 file changed, 2 insertions(+)
 create mode 100644 vulcan.py

  切回dev,準備合並:

$ git checkout dev

銷毀

$ git branch -d  dev-vulcan
error: The branch dev-vulcan is not fully merged.
If you are sure you want to delete it, run git branch -D dev-vulcan.

  銷毀失敗。Git友情提醒,dev-vulcan分支還沒有被合並,如果刪除,將丟失掉修改,如果要強行刪除,需要使用大寫的-D參數。

$ git branch -D dev-vulcan
Deleted branch dev-vulcan (was 287773e).

參考:https://blog.51cto.com/wangfeng7399/2352662

二.多人協作

  克隆倉庫的命令格式是git clone [url]

$ git clone https://github.com/libgit2/libgit2

   自定義本地倉庫的名字,你可以使用如下命令:

$ git clone https://github.com/libgit2/libgit2 mylibgit

  發生沖突時:先pull,在本地合並,然後才能push成功。合並後,分支變成了下面:

$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
*   e5e69f1 Merge branch dev
|\  
| *   57c53ab (origin/dev, dev) fix env conflict
| |\  
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/  
* |   12a631b merged bug fix 101
|\ \  
| * | 4c805e2 fix bug 101
|/ /  
* |   e1e9c68 merge with no-ff
|\ \  
| |/  
| * f52c633 add merge
|/  
*   cf810e4 conflict fixed

  Git有一種稱為rebase的操作,有人把它翻譯成“變基”

  在和遠程分支同步後,我們對hello.py這個文件做了兩次提交。用git log命令看看:

$ git log --graph --pretty=oneline --abbrev-commit
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello
*   e5e69f1 Merge branch dev
|\  
| *   57c53ab (origin/dev, dev) fix env conflict
| |\  
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
...

  推送本地分支:

$ git push origin master
To github.com:michaelliao/learngit.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to [email protected]:michaelliao/learngit.git
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., git pull ...) before pushing again.
hint: See the Note about fast-forwards in git push --help for details.

這樣就失敗了,這說明有人先於我們推送了遠程分支。按照經驗,先pull一下:

$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
   d1be385..f005ed4  master     -> origin/master
 * [new tag]         v1.0       -> v1.0
Auto-merging hello.py
Merge made by the recursive strategy.
 hello.py | 1 +
 1 file changed, 1 insertion(+)

  再用git status看看狀態:

$ git status
On branch master
Your branch is ahead of origin/master by 3 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

  git log看看:

$ git log --graph --pretty=oneline --abbrev-commit
*   e0ea545 (HEAD -> master) Merge branch master of github.com:michaelliao/learngit
|\  
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/  
* d1be385 init hello
...

現在把本地分支push到遠程,有沒有問題?有,不好看

  輸入命令git rebase試試:

$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M    hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M    hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py

  再用git log看看:

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
...

  最後,通過push操作把本地分支推送到遠程:

Mac:~/learngit michael$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:michaelliao/learngit.git
   f005ed4..7e61ed4  master -> master

  再用git log看看效果:

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=1
* d1be385 init hello
...

遠程分支

1.推送

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

抓取數據時

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

如果想要在自己的 serverfix分支上工作,可以將其建立在遠程跟蹤分支之上:

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch serverfix

2.跟蹤分支

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch serverfix

  如果想要將本地分支與遠程分支設置為不同名字,你可以輕松地增加一個不同名字的本地分支的上一個命令:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch sf

  設置已有的本地分支跟蹤一個剛剛拉取下來的遠程分支,或者想要修改正在跟蹤的上遊分支,你可以在任意時間使用 -u--set-upstream-to 選項運行 git branch 來顯式地設置。

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.

  如果想要查看設置的所有跟蹤分支,可以使用 git branch-vv 選項

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new

3.刪除遠程分支

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

參考:https://blog.51cto.com/wangfeng7399/2352667

三.忽略特殊文件

1.忽略特殊文件的原則:

  1. 忽略操作系統自動生成的文件,比如縮略圖等;
  2. 忽略編譯生成的中間文件、可執行文件等,也就是如果一個文件是通過另一個文件自動生成的,那自動生成的文件就沒必要放進版本庫,比如Java編譯產生的.class文件;
  3. 忽略你自己的帶有敏感信息的配置文件,比如存放口令的配置文件。

有些時候,你想添加一個文件到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

  可以用git check-ignore命令檢查:

$ git check-ignore -v App.class
.gitignore:3:*.class    App.class

  .gitignore的第3行規則忽略了該文件,於是我們就可以知道應該修訂哪個規則。

    忽略某些文件時,需要編寫.gitignore

    .gitignore文件本身要放到版本庫裏,並且可以對.gitignore做版本管理!

四.標簽的管理

1.列出標簽

$ git tag
v0.1
v1.3

  如果只對 1.8.5 系列感興趣,可以運行:

$ git tag -l v1.8.5*
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5-rc2
v1.8.5-rc3
v1.8.5.1
v1.8.5.2
v1.8.5.3
v1.8.5.4
v1.8.5.5

2.創建標簽

  輕量標簽(lightweight)與附註標簽(annotated)

  2.1 附註標簽 附註標簽是存儲在 Git 數據庫中的一個完整對象

$ git tag -a v1.4 -m my version 1.4
$ git tag
v0.1
v1.3
v1.4

  -m 選項指定了一條將會存儲在標簽中的信息

  通過使用 git show 命令可以看到標簽信息與對應的提交信息:

$ git show v1.4
tag v1.4
Tagger: Ben Straub <[email protected]>
Date:   Sat May 3 20:19:12 2014 -0700

my version 1.4

commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

  2.2 輕量標簽 輕量標簽本質上是將提交校驗和存儲到一個文件中 - 沒有保存任何其他信息

$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5

  如果在標簽上運行 git show,你不會看到額外的標簽信息。 命令只會顯示出提交信息:

$ git show v1.4-lw
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

3.後期打標簽

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch experiment
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch experiment
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

  假設在 v1.2 時你忘記給項目打標簽,也就是在 “updated rakefile” 提交。 你可以在之後補上標簽。 要在那個提交上打標簽,你需要在命令的末尾指定提交的校驗和(或部分校驗和):

$ git tag -a v1.2 9fceb02

4.共享標簽

$ git push origin v1.5
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To [email protected]:schacon/simplegit.git
 * [new tag]         v1.5 -> v1.5

  如果想要一次性推送很多標簽,也可以使用帶有 --tags 選項的 git push 命令

$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To [email protected]:schacon/simplegit.git
 * [new tag]         v1.4 -> v1.4
 * [new tag]         v1.4-lw -> v1.4-lw

5.刪除標簽

  要刪除掉你本地倉庫上的標簽,可以使用命令 git tag -d &lt;tagname&gt;

  可以使用下面的命令刪除掉一個輕量級標簽:

$ git tag -d v1.4-lw
Deleted tag v1.4-lw (was e7d5add)

  應該註意的是上述命令並不會從任何遠程倉庫中移除這個標簽,你必須使用 git push &lt;remote&gt; :refs/tags/&lt;tagname&gt; 來更新你的遠程倉庫:

$ git push origin :refs/tags/v1.4-lw
To /[email protected]:schacon/simplegit.git
 - [deleted]         v1.4-lw

6. 檢出標簽

  如果你想查看某個標簽所指向的文件版本,可以使用 git checkout 命令

參考:https://blog.51cto.com/wangfeng7399/2352670

git的分支,多人協作,標簽管理