Feature Branching

最流行的工作流。

Start

Summary

这种工作流的核心内容可以总结为两点:

  1. 任何新的功能(feature)或 bug 修复全都新建一个 branch 来写;
  2. branch 写完后,合并到 master,然后删掉这个 branch

Feature Branching 这种工作流,为团队开发时两个关键的问题——代码分享和一人多任务——提供了解决方案。

此处建议新起仓库模拟多人进行实际操作。以下不仅有checkout练习,还涉及pull,merge等操作。

1. 代码分享

colleague

1
2
3
4
此前我的仓库,和新建同事a的仓库应该是一样的。还需要在同时新建同事b,他要在一切前要push origin master到6
git checkout -b books
-----after n commits
git push origin books
本地实际从master开始checkout写,所以直线 但此时经过其他同事origin/master已经到6

Me

1
2
3
4
5
6
7
8
9
10
git pull
git chekcout books
---看了没问题
git checkout master
git pull # merge 之前 pull 一下,让 master 更新到和远程仓库同步
git merge books
---合并后
git push
git branch -d books
git push origin -d books # 用 -d 参数把远程仓库的 branch 也删了

模拟

目前模拟:

git-a

注意三个仓库的起点都是红框处。

a在原来的基础上,新建一条分支进行开发。并完成两次的本地提交。

3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
➜  git-exercise-a git:(main) git checkout -b test-a
Switched to a new branch 'test-a'
➜ git-exercise-a git:(test-a) git add .
➜ git-exercise-a git:(test-a) ✗ git commit -m "分支a 第一次提交"
[test-a a0a68fe] 分支a 第一次提交
1 file changed, 2 insertions(+)
create mode 100644 branch-a-1.txt
➜ git-exercise-a git:(test-a) git status
On branch test-a
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: branch-a-1.txt

no changes added to commit (use "git add" and/or "git commit -a")
➜ git-exercise-a git:(test-a) ✗ git add .
➜ git-exercise-a git:(test-a) ✗ git commit -m "分支a 第 2 次提交"
[test-a 17ff65f] 分支a 第 2 次提交
1 file changed, 1 insertion(+)
➜ git-exercise-a git:(test-a) git log
➜ git-exercise-a git:(test-a) git push origin test-a
remote: Create a pull request for 'test-a' on GitHub by visiting:
remote: https://github.com/cutegentle/git-exercise/pull/new/test-a
remote:
To github.com:cutegentle/git-exercise.git
* [new branch] test-a -> test-a
git-exercise

最后git-exercise将模拟pull的本质。当前HEAD在起点处,尚未修改。

4
git-b

b做的变化就是在main上提交一次并push到origin

5

一切准备就绪。我就是下图。还在之前的版本。main落后一个,没有testa分支。

6
1
2
3
4
5
6
7
➜  git-exercise git:(main) git pull
Updating 68a8e97..942f1d3
Fast-forward
b-main-ahead1.txt | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 b-main-ahead1.txt
git log 会显示到最新的main,所有main上引用都到最新版本。
7
1
2
3
4
5
6
7
8
此时可以明确看到,test-a在本地仍没有,那么真的没有吗?
➜ git-exercise git:(main) git checkout test-a
Branch 'test-a' set up to track remote branch 'test-a' from 'origin'.
Switched to a new branch 'test-a'
直接切换分支即可,Git会自动建立分支来追踪远程的分支。
在当前分支查看git log
commit 17ff65f25dba46a086f53b2516fdf6e563b848c0 (HEAD -> test-a, origin/test-a)
在此再次提醒:branch本质是一串 commits
8

至此,对于原来白板的git-exercise仓库。main分支更新到最新,同时也获取到远程的其他分支。

我在test-a分支上阅读了同事的代码。

9

觉得还是不错的。就合并。

1
2
3
4
5
6
7
8
➜  git-exercise git:(test-a) git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.会先提示你要不要在merge前pull
➜ git-exercise git:(main) git merge test-a
Merge made by the 'recursive' strategy.
branch-a-1.txt | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 branch-a-1.txt
10

11

12

在main上git log查看发现,多出三个commits,因此会提示main分支上超前三个版本。merge会产生一次新的额外commit这里先说明,之后细说。

13

1
2
3
git pull 目前我只运用在main上,因为最方便直接。会拉取所有remote的最新代码,本地没有的分支会自动创建。
git push 就看上图,理解为默认只推送当前分支。一般在本地main上merge后直接push即可。
之后有空研究下在其他分支进行操作会怎么样。在其他分支上是不能简写成git push的
14
1
2
3
4
5
➜  git-exercise git:(main) git branch -d test-a 
Deleted branch test-a (was 17ff65f).
➜ git-exercise git:(main) git push origin -d test-a
To github.com:cutegentle/git-exercise.git
- [deleted] test-a
15

删除本地分支,删除远程分支。实际删除的只是引用,提交还是在的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
同事:
git checkout -b books
---after n commits
git push origin books

# 我:
git pull
git chekcout books
---看了没问题
git checkout master
git pull # merge 之前 pull 一下,让 master 更新到和远程仓库同步
git merge books
---合并后
git push
git branch -d books
git push origin -d books # 用 -d 参数把远程仓库的 branch 也删了

pull request后续介绍。

2. what is git pull

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
NAME
git-pull - Fetch from and integrate with another repository or a local branch

SYNOPSIS
git pull [<options>] [<repository> [<refspec>...]]


DESCRIPTION
Incorporates changes from a remote repository into the current branch. In its default mode, git pull is
shorthand for git fetch followed by git merge FETCH_HEAD.

More precisely, git pull runs git fetch with the given parameters and calls git merge to merge the retrieved
branch heads into the current branch. With --rebase, it runs git rebase instead of git merge.

<repository> should be the name of a remote repository as passed to git-fetch(1). <refspec> can name an
arbitrary remote ref (for example, the name of a tag) or even a collection of refs with corresponding
remote-tracking branches (e.g., refs/heads/*:refs/remotes/origin/*), but usually it is the name of a branch in
the remote repository.

Default values for <repository> and <branch> are read from the "remote" and "merge" configuration for the
current branch as set by git-branch(1) --track.

Assume the following history exists and the current branch is "master":

A---B---C master on origin
/
D---E---F---G master
^
origin/master in your repository


Then "git pull" will fetch and replay the changes from the remote master branch since it diverged from the local
master (i.e., E) until its current commit (C) on top of master and record the result in a new commit along with
the names of the two parent commits and a log message from the user describing the changes.

:

3. see commit

1
2
3
4
5
6
git log
git log -p
git log --stat
git show
git show 953f #至少4位
git diff --staged

这一节介绍了一些查看改动内容的方法,大致有这么几类:

  1. 查看历史中的多个commit:log
    1. 查看详细改动: git log -p
    2. 查看大致改动:git log --stat
  2. 查看具体某个commit :show
    1. 要看最新 commit ,直接输入 git show ;要看指定 commit ,输入 git show commit的引用或SHA-1
    2. 如果还要指定文件,在 git show 的最后加上文件名
  3. 查看未提交的内容:diff
    1. 查看暂存区和上一条 commit 的区别:git diff --staged(或 --cached
    2. 查看工作目录和暂存区的区别:git diff 不加选项参数
    3. 查看工作目录和上一条 commit 的区别:git diff HEAD

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!