06 Git 分支管理
By Kevin Song
- 06-01 创建与合并分支
- 06-02 解决冲突
- 06-03 分支管理策略
- 06-04 存储工作区
- 06-05 Feature分支
- 06-06 多人协作
分支作用:
- 主分支不能一直在修改(会导致项目中其他人不能干活)
- 主分支不能一次性推送(会导致一个篮子里鸡蛋都碎了)
- 创建一个新分支
- 在新分支中工作
- 随时提交
- 开发完合并到Master Branch
06-01 创建与合并分支
1 . 创建分支
$ git branch dev
2 . 切换分支
$ git checkout dev
Switched to branch 'dev'
第一第二步可以合并成一句:
$ git checkout -b dev
Switched to a new branch 'dev'
3 . 查看当前分支
- 当前分支前有星号
$ git branch
* dev
master
4 . 修改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(+)
5 . 切换回master分支
$ git checkout master
Switched to branch 'master'
6 . 合并dev分支到master分支
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
7 . 删除dev分支
$ git branch -d dev
Deleted branch dev (was fec145a).
06-02 解决冲突
两个分支的同一个文件做了不同修改导致 冲突
feature1分支修改readme.txt
$ git checkout -b feature1
Switched to a new branch 'feature1'
Creating a new branch is quick AND simple.
$ git add readme.txt
$ git commit -m "AND simple"
[feature1 75a857c] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
master分支修改readme.txt
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
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 merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
直接查看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
修改如下后保存:
Creating a new branch is quick and simple.
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master 59bc1cb] conflict fixed
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).
06-03 分支管理策略
合并分支默认使用Fast forward 模式
Fast Forward 缺点:删除分支后,会丢掉分支信息
禁用Fast forward模式
1 . 创建并切换dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
2 . 修改readme.txt文件,并提交一个新的commit:
$ git add readme.txt
$ git commit -m "add merge"
[dev 6224937] add merge
1 file changed, 1 insertion(+)
3 . 切换回master:
$ git checkout master
Switched to branch 'master'
4 . 合并dev分支
- –no-ff参数:禁用Fast forward
- -m参数:添加commit描述
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
分支策略
- master分支:只用来发布新版本,不用来开发
- dev分支:用来开发
- 每个人在dev分支上开发,每个人都有自己的分支,时不时往dev分支上合并
- dev分支:用来开发
06-04 存储工作区
git stash存储当前工作区
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
git stash list查看存储的工作区:
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
恢复方法一: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} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
06-05 Feature分支
新建一个新功能分支,开发完再合并到master branch
$ git checkout -b feature-vulcan
Switched to a new branch 'feature-vulcan'
开发完毕
$ git add vulcan.py
$ git status
# On branch feature-vulcan
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: vulcan.py
#
$ git commit -m "add feature vulcan"
[feature-vulcan 756d4af] add feature vulcan
1 file changed, 2 insertions(+)
create mode 100644 vulcan.py
切回dev,准备合并:
$ git checkout dev
突然要销毁该分支
$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
删不了,只能强制删除
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 756d4af).
06-06 多人协作
git remote 查看远程仓库信息
$ git remote
origin
git remote -v 查看详细远程仓库信息
$ git remote -v
origin git@github.com:KevinJtSong/learngit.git (fetch)
origin git@github.com:KevinJtSong/learngit.git (push)
推送分支
推送master branch
$ git push origin master
推送dev branch
$ git push origin dev
分支种类
- master branch:时刻与远程同步
- dev branch:时刻与远程同步
- bug branch:只用于在本地修复bug,不需要推送
- feature
抓取分支
同事A克隆了仓库
$ git clone git@github.com:michaelliao/learngit.git
Cloning into 'learngit'...
remote: Counting objects: 46, done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 46 (delta 16), reused 45 (delta 15)
Receiving objects: 100% (46/46), 15.69 KiB | 6 KiB/s, done.
Resolving deltas: 100% (16/16), done.
同事A只能看到master branch
$ git branch
* master
同事A要在dev分支上开发必须创建origin的dev分支到本地
$ git checkout -b dev origin/dev
同事A把dev分支push到远程:
$ git commit -m "add /usr/bin/env"
[dev 291bea8] add /usr/bin/env
1 file changed, 1 insertion(+)
$ git push origin dev
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 349 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:KevinJtSong/learngit.git
fc38031..291bea8 dev -> dev
同事B对同样的文件作了修改,并试图推送:
$ git add hello.py
$ git commit -m "add coding: utf-8"
[dev bd6ae48] add coding: utf-8
1 file changed, 1 insertion(+)
$ git push origin dev
To git@github.com:KevinJtSong/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:KevinJtSong/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
推送失败,必须先
用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
fc38031..291bea8 dev -> origin/dev
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 dev origin/<branch>
git pull也失败,原因是没有指定本地dev分支与远程origin/dev分支的链接,先设置dev和origin/dev的链接:
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
再pull:
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push:
$ git commit -m "merge & fix hello.py"
[dev adca45d] merge & fix hello.py
$ git push origin dev
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 747 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
291bea8..adca45d dev -> dev
多人协作 工作模式
- 用git push origin branch-name推送自己的修改
- 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并
- 如果合并有冲突,则解决冲突,并在本地提交
- 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功