git-logo

第三部分 分支

Created by Charles Liu

Agenda

  • 查看分支
  • 创建分支
  • 切换分支
  • 合并分支
  • 复用commit
  • 冲突解决

查看本地分支

git branch

切换到emoji-minesweeper目录, 查看分支


repository $ cd emoji-minesweeper
emoji-minesweeper $ git branch
* master
  

查看全部分支

git branch --all

切换到emoji-minesweeper目录, 查看分支


$ git branch --all
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/gh-pages
  remotes/origin/master
  remotes/origin/randos
    

创建分支

git branch new_branch_name

# In todo list git
$ git branch testing
$ git branch
* master
  testing
  
branch status before creating branch

创建前

branch status after creating branch

创建后

切换分支

git checkout branch-name

$ git checkout testing
$ git branch
  master
* testing
    
branch status before switching branch

切换前

branch status after switching branch

切换后

创建并切换到新分支

git checkout -b new-branch-name

下述两组命令等价:


$ git branch testing
$ git checkout testing
    

$ git checkout -b testing
    

在新分支上提交代码


$ echo "# Shopping list" >> shopping.md
$ echo "" >> shopping.md # blank line
$ git add .
# . 意思是暂存当前目录及子目录下所有变化, 包括未跟踪状态下的文件
$ git commit -m "Add shopping list title"
    

master 和 testing这两个分支上的状态会有什么不同?

branch status before commit

提交前

branch status after commit

提交后

通过git shell查看多分支间commit之间的关系

git log --all

$ git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
* 0ba7b40 - (HEAD -> testing, origin/master, origin/HEAD, master) kiwi (3 weeks ago) <Xingchao Liu>
*   3a3543f - Merge branch 'soy-milk' (3 weeks ago) <Xingchao Liu>
|\
| * de1fef2 - (origin/soy-milk) charles wants soy-milk (3 weeks ago) <Charles Liu>
* | 7aa2e2e - (origin/apple) buy apple (3 weeks ago) <Charles Liu>
|/
* 2e64ee8 - orange (3 weeks ago) <Charles Liu>
* 65a9ca6 - milk (3 weeks ago) <Charles Liu>
* 358c3a0 - (origin/bbb) 添加一个标题 (3 weeks ago) <Charles Liu>
    

可以通过配置别名简化输入. 见配置别名

通过gitk图形界面查看分支关系

gitk --all

$ gitk --all
    
gitk --all

切换分支对文件系统的影响


$ gitk checkout master
$ cat shopping.md
cat: shopping.md: No such file or directory
    
切换分支会改变文件系统. 工作区的目录结构和文件内容都会变到对应的分支最后一次提交的状态.

有未提交的改动时切换工作区版本


$ git checkout testing
$ echo "Buy an apple" >> shopping.md
$ git checkout testing
error: Your local changes to the following files would be overwritten by checkout:
    shopping.md
Please commit your changes or stash them before you can switch branches.
Aborting
    

储藏已修改的文件

git stash

$ git stash
Saved working directory and index state WIP on testing: 7c83fe6 Add shopping list title
HEAD is now at 7c83fe6 Add shopping list title
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
    

要储藏Untracked文件, 需要用--include-untracked参数

把储藏的文件应用回工作区


$ git stash pop
On branch testing
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:   shopping.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (6efa6ecc509655f4f8d59b7c4cc37417de0a8c08)
    

合并分支

git merge branch_name (to current branch)

分支初始状态

graph LR a((a))-->b((b)) b-->c((c)) d((d))-->e((e)) e-->f((f)) f---x(master) c---y(topic) e-->a class x,y branchClass;

普通合并

graph LR a((a))-->b((b)) b-->c((c)) d((d))-->e((e)) c-->m((M)) e-->f((f)) f-->m m---y(master/topic) e-->a class y branchClass style m fill:yellow;

分支实例


$ git checkout -b soy-milk
$ # Change milk to soy-milk
$ git add .
$ git commit "charles wants soy-milk"
$ git checkout master
$ echo "buy apple" >> Readme.md
$ git add .
$ git commit -m "buy apple"
$ git lg --all
    

* 59f6d63 - (HEAD -> master) buy apple(6 seconds ago) <Charles Liu>
| * f46bd2d - (soy-milk) Charles wants soy milk (2 minutes ago) <Charles Liu>
|/
* bd36223 - orange (3 hours ago) <Charles Liu>
* e4a2762 - Milk (3 hours ago) <Charles Liu>
| * 91292e5 - (todo) training (3 hours ago) <Charles Liu>
|/
* a2ce87d - Add Readme Title (3 hours ago) <Charles Liu>
    

分支实例——合并


$ git checkout master
$ git merge soy-milk
    

跳转到Commit Message编辑界面, 用默认Message.


$ git lg --all
*   7c53e8c - (HEAD -> master) Merge branch 'soy-milk' (15 seconds ago) <Charles Liu>
|\
| * f46bd2d - (soy-milk) Charles wants soy milk (14 minutes ago) <Charles Liu>
* | ad76997 - buy apple (34 seconds ago) <Charles Liu>
|/
* bd36223 - orange (3 hours ago) <Charles Liu>
* e4a2762 - Milk (3 hours ago) <Charles Liu>
| * 91292e5 - (todo) training (3 hours ago) <Charles Liu>
|/
* a2ce87d - Add Readme Title (3 hours ago) <Charles Liu>
    

fast-forward merge

分支初始状态

graph LR a((a))-->b((b)) b-->c((c)) d((d))-->e((e)) e---x(master) c---y(topic) e-->a class x,y branchClass;

普通合并

graph LR a((a))-->b((b)) b-->c((c)) d((d))-->e((e)) c-->m((M)) e-->m m---y(master/topic) e-->a class y branchClass style m fill:yellow;

Fast-Forward合并

graph LR a((a))-->b((b)) b-->c((c)) d((d))-->e((e)) e-->a c---y(master/topic) class y branchClass

变基(Rebase)分支

git rebase ref_branch_name

分支初始状态

graph LR d((d))-->e((e)) e-->f((f)) f-->g((g)) e-->a((a)) a-->b((b)) b-->c((c)) c---topic(topic) g---master(master) class topic,master branchClass

变基后

graph LR d((d))-->e((e)) e-->f((f)) f-->g((g)) a((a'))-->b((b')) b-->c((c')) g-->a c---topic(topic) g---master(master) class topic,master branchClass

冲突解决

git mergetool

安装配置Kdiff3

Mac & Windows

Download: https://sourceforge.net/projects/kdiff3/files/kdiff3/0.9.98/
安装路径最好不要有空格
在${HOME}/.gitconfig文件中添加下述配置:


[merge]
    tool = kdiff3
[mergetool "kdiff3"]
    path = /Applications/kdiff3.app/Contents/MacOS/kdiff3
(/cygdrive/c/kdiff3/kdiff3.exe)
    

Ubuntu


$ sudo apt-get install kdiff3
$ vim ~/.gitconfig

# Add following:
[merge]
tool = kdiff3
    

解决一个冲突

在todo-list代码库中


$ git checkout todo
$ git checkout master
$ git merge todo
Auto-merging Readme.md
CONFLICT (content): Merge conflict in Readme.md
Automatic merge failed; fix conflicts and then commit the result.
    

$ git mergetool
    

kdiff3工作界面

gitk
gitk

kdiff3操作

选C, 选B, 保存退出


$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)

Changes to be committed:

modified:   Readme.md

Untracked files:
(use "git add <file>..." to include in what will be committed)

Readme.md.orig
    

执行rm Readme.md.orig删除生成的备份文件
或者执行git clean -f删除所有untracked files


$ git commit
# 跳转到VIM, 使用默认Commit Message. :wq退出
$ git lg
*   b637fe8 - (HEAD -> master) Merge branch 'todo' (8 seconds ago) <Charles Liu>
|\
| * 14e2113 - (origin/todo, todo) training (20 hours ago) <Charles Liu>
* | 2e64ee8 - (origin/master, origin/HEAD) orange (20 hours ago) <Charles Liu>
* | 65a9ca6 - milk (20 hours ago) <Charles Liu>
|/
* 358c3a0 - (origin/bbb) 添加一个标题 (21 hours ago) <Charles Liu>
    

删除分支

git branch -d branch_name [--force]