mydal

怕光阴流逝 让一切都作废

0%

git那些事

​ 在日常开发中,git是我们不可或缺的工具,作为一个优秀的版本控制工具,值得学习的地方还是很多的.趁这次学习git flow的机会,也重新学习一下git基本命令,好记性不如烂笔头,多写多练,才能在实际开发中游刃有余的使用git.

git基本命令

新建代码库

1
2
3
4
5
6
7
8
# 在当前目录新建一个 Git 代码库
git init

# 新建一个目录,将其初始化为 Git 代码库
git init [project-name]

# 下载一个项目和它的整个代码历史
git clone [url]

增加/删除文件

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
38
# 添加指定文件到暂存区
git add [file1] [file2] ...

# 添加指定目录到暂存区,包括子目录
git add [dir]

# 添加当前目录的所有文件到暂存区
git add .

# 删除工作区文件,并且将这次删除放入暂存区
git rm [file1] [file2] ...

# 停止追踪指定文件,但该文件会保留在工作区
git rm --cached [file]

# 改名文件,并且将这个改名放入暂存区
git mv [file-original] [file-renamed]


代码提交
# 提交暂存区到仓库区
git commit -m [message]

# 提交暂存区的指定文件到仓库区
git commit [file1] [file2] ... -m [message]

# 提交工作区自上次 commit 之后的变化,直接到仓库区
git commit -a

# 提交时显示所有 diff 信息
git commit -v

# 使用一次新的 commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次 commit 的提交信息
git commit --amend -m [message]

# 重做上一次 commit,并包括指定文件的新变化
git commit --amend ...

分支操作

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
38
39
# 列出所有本地分支
git branch

# 列出所有远程分支
git branch -r

# 列出所有本地分支和远程分支
git branch -a

# 新建一个分支,但依然停留在当前分支
git branch [branch-name]

# 新建一个分支,并切换到该分支
git checkout -b [branch]

# 新建一个分支,指向指定 commit
git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
git branch --track [branch] [remote-branch]

# 切换到指定分支,并更新工作区
git checkout [branch-name]

# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支
git merge [branch]

# 选择一个 commit,合并进当前分支
git cherry-pick [commit]

# 删除分支
git branch -d [branch-name]

# 删除远程分支
git push origin --delete
git branch -dr

查看信息

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
38
39
40
41
# 显示有变更的文件
git status

# 显示当前分支的版本历史
git log

git log --pretty=oneline # 使用不同于默认格式的方式展示提交历史
git log --online # 简洁展示历史
git log --oneline --all # 分支所有呈现
git log --stat # 显示 commit 历史,以及每次 commit 发生变更的文件交
git log -p [file] # 显示指定文件相关的每一次 diff
git log -p -2 # 展示最近的两次提交
git log -n4 --online # 看最近的历史消息
git branch -v # 看本地有多少分支
git checkout -b dashu 223343232 # 分支 , 修改分支

# 显示暂存区和工作区的差异
git diff

# 显示暂存区和上一个 commit 的差异
git diff --cached []

# 显示工作区与当前分支最新 commit 之间的差异
git diff HEAD

# 显示两次提交之间的差异/两个分支的比较
git diff [first-branch]...[second-branch]
git diff test master # 本地和本地
git diff test origin/test # 本地和远程

# 显示某次提交的元数据和内容变化
git show [commit]

# 显示某次提交发生变化的文件
git show --name-only [commit]

# 显示某次提交时,某个文件的内容
git show [commit]:[filename]

# 显示当前分支的最近几次提交
git reflog

远程同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 下载远程仓库的所有变动
git fetch [remote]

# 显示所有远程仓库
git remote -v

# 显示某个远程仓库的信息
git remote show [remote]

# 增加一个新的远程仓库,并命名
git remote add [shortname] [url]

# 取回远程仓库的变化,并与本地分支合并
git pull [remote] [branch]

# 上传本地指定分支到远程仓库
git push [remote] [branch]

# 强行推送当前分支到远程仓库,即使有冲突
git push [remote] --force

# 推送所有分支到远程仓库
git push [remote] --all

git-flow的工作流程

什么是git-flow?

git-flow是一个git工作流,这里借鉴网上的一些说明:

​ Giflow 是另一种 Git 分支模型,它涉及使用功能分支和多个主分支。它由文森特·德里森( Vincent Driessen) 在 nvie首次出版并广受欢迎。与基于主干的开发相比,Giflow 拥有众多、寿命更长的分支和更大的提交。在这个模型下,开发者创建一个功能分支,并延迟合并到主干分支,直到功能完成。这些长期存在的特性分支需要更多的协作来合并,并且有更高的偏离主干分支的风险。它们还可以引入冲突的更新。

​ Gitflow可用于有计划的发布周期项目和为DevOps的最佳实践持续交付。除了Feature Branch Workflow所需的内容之外,此工作流不会添加任何新概念或命令 。相反,它为不同的分支分配非常具体的角色,并定义它们应该如何以及何时交互。除了feature分支之外,它还使用单独的分支来准备、维护和记录发布。当然,您还可以利用 Feature Branch Workflow 的所有优势:拉取请求、独立实验和更高效的协作。

入门

​ Git-flow 是 Git 的包装器。该git flow init命令是默认git init 命令的扩展,除了为创建分支外,不会更改存储库中的任何内容。

运行

​ 当在项目的根目录执行”git flow init“命令时 当前项目是否已经包括了一个Git仓库并不重要。因为git flow只是一个工作流,不会添加任何新概念和命令。所以,在一个项目中,可以先执行git init,再执行git flow init,当然,这是很没有必要的.

分支的模式

git-flow 模式会预设两个主分支在仓库中:

master 只能用来包括产品代码. 不能直接在这个分支上工作. 而是在其他指定的,独立的特性分支中进行工作. 不直接提交到master分支上是很多工作流程的一个共同的规则。

develop 是你进行任何新的开发的基础分支。当你开始一个新的功能分支时,它将是开发的基础。另外,该分支也应该汇集所有已经完成的功能,并等待被整合到 master分支中。

​ 这两个分支被称为长期分支。它们会存活在项目的整个生命周期中。而其他的分支,如针对功能的分支,针对发行的分支,只是临时存在。它们是根据你的需求来创建的,完成任务之后就删除掉.

简单使用

功能开发

​ 对于一个开发人员来说,最平常的工作就是项目功能的开发。所以我们可以使用git-flow这个工作流,它定义了很多对于功能开发的工作流程

开始新功能

现在我们开始开发项目的一个新功能"oss-upload"

1
2
3
4
5
6
$ git flow feature start oss-upload
Switched to a new branch 'feature/oss-upload'

Summary of actions:
- A new branch 'feature/oss-upload' was created, based on 'develop'
- You are now on branch 'feature/oss-upload'

​ 这时,git-flow会创建一个名为”feature/oss-upload”的新分支,并自动切换到该分支,我们直接就可以开始工作了.

完成一个功能

经过艰苦的工作,我们的新功能终于开发完成了:

1
2
3
4
5
6
7
8
9
$ git flow feature finish oss-upload
Switched to branch 'develop'
Already up to date.
Deleted branch feature/oss-upload (was 996bb46).

Summary of actions:
- The feature branch 'feature/oss-upload' was merged into 'develop'
- Feature branch 'feature/oss-upload' has been locally deleted
- You are now on branch 'develop'

​ ‘flow feature finish’会把我们添加或修改的新功能合并到’develop’分支中去.并且会删除这个当前已经完成工作的分支’feature/oss-upload’,并自动切换到’develop分支’

管理releases

​ Release 管理是版本控制处理中的另外一个非常重要的话题。让我们来看看如何利用 git-flow 创建和发布 release。

创建release

​ 当我们的 “develop” 分支的代码已经是一个成熟的 release 版本时,这意味着:第一,它包括所有新的功能和必要的修复;第二,它已经被彻底的测试过了。如果上述两点都满足,那就是时候开始生成一个新的 release 了:

1
2
$ git flow release start 0.0.1
Switched to a new branch 'release/0.0.1'

​ 执行完这条命令之后,我们发现release 分支是使用版本号命名的。这个命名方案还有一个很好的附带功能,那就是当我们完成了release 后,git-flow 会适当地自动去标记那些 release 提交。

完成release
1
2
3
4
5
6
7
8
$ git flow release finish 0.0.1
Deleted branch release/0.0.1 (was 996bb46).

Summary of actions:
- Release branch 'release/0.0.1' has been merged into 'master'
- The release was tagged '0.0.1'
- Release branch 'release/0.0.1' has been locally deleted
- You are now on branch 'develop'

这个命令会完成如下一系列的操作:

  1. 首先,git-flow 会拉取远程仓库,以确保目前是最新的版本。
  2. 然后,release 的内容会被合并到 “master” 和 “develop” 两个分支中去,这样不仅产品代码为最新的版本,而且新的功能分支也将基于最新代码。
  3. 为便于识别和做历史参考,release 提交会被标记上这个 release 的名字
  4. 清理操作,版本分支会被删除,并且回到 “develop”。

hotfix

​ 很多时候,仅仅在几个小时或几天之后,当对 release 版本作做全面测试时,可能就会发现一些bug。
在这种情况下,git-flow 提供一个特定的 “hotfix” 工作流程(因为在这里不管使用 “功能” 分支流程,还是 “release” 分支流程都是不恰当的)。

创建Hotfixes
1
$ git flow hotfix start missing-link

​ 这个命令会创建一个名为 “hotfix/missing-link” 的分支。因为这是对产品代码进行修复,所以这个 hotfix 分支是基于 “master” 分支。
这也是和 release 分支最明显的区别,release 分支都是基于 “develop” 分支的。因为你不应该在一个还不完全稳定的开发分支上对产品代码进行地修复。

就像 release 一样,修复这个错误当然也会直接影响到项目的版本号!

完成Hotfixes
1
$ git flow hotfix finish missing-link

这个过程非常类似于发布一个 release 版本:

  • 完成的改动会被合并到 “master” 中,同样也会合并到 “develop” 分支中,这样就可以确保这个错误不会再次出现在下一个 release 中。
  • 这个 hotfix 程序将被标记起来以便于参考。
  • 这个 hotfix 分支将被删除,然后切换到 “develop” 分支上去。

总结一下

​ 首先,git-flow不会为git扩展新的功能,只是用来完成一些特定的工作流程。其次,定义一个固定的工作流程会使团队合作更加简单容易.最后,我们可以使用feature来开发功能,release来发布版本,最后可以通过hotfix来修改产品代码的bug.感觉理解的不太对,但又有点说不上来,等实际开发中用到应该就可以加深一点理解.