Git 的正确使用姿势与最佳实践-团队协作和版本控制 | 青训营

638 阅读7分钟

Git的基本概念

分布式版本控制系统

分布式版本控制系统相较于集中版本控制,它的特点是每个库完整地保存了代码提交历史,并且每次提交都记录了完整的文件快照而非Diff增量。这就较好地支持了本地提交和团队协助能力。同时很好地保证了代码的完整性和安全性。不过这也意味着带来了更高的学习成本和更多的存储空间的消耗。

Git

Git 是一个分布式版本控制系统,它的核心是一个对象数据库,这个数据库中存储了所有的版本信息,包括文件的内容、文件的路径、文件的状态等等。Git 通过对这些信息的操作,来实现版本控制的功能。

基本概念

仓库(Repository): 仓库是Git中最基本的概念,它是一个目录,用于存放项目的文件和元数据。仓库可以分为本地仓库和远程仓库。本地仓库是指存放在本地计算机上的仓库,远程仓库是指存放在远程服务器上的仓库。

提交(Commit): 提交是Git中最基本的操作,它是对仓库中的文件进行修改后的保存操作。每次提交都会生成一个唯一的提交ID,用于标识这次提交。提交ID是一个40位的十六进制字符串,它是通过对提交的内容进行SHA-1哈希计算得到的。

分支(Branch): 分支是Git中用于实现并行开发的功能。每个分支都是一个独立的代码版本,它们之间相互独立,互不影响。分支可以用于实现新功能的开发,也可以用于修复bug。

标签(Tag): 标签是Git中用于标记某个提交的功能。标签可以用于标记项目的版本,也可以用于标记项目的里程碑。标签和分支一样,都是指向某个提交的指针,它们之间的区别是,分支可以移动,而标签不可以移动。

基本操作

以下是一些常用的 Git 命令:(参见:git help)

  • 开始一个工作区(参见:git help tutorial) clone 克隆一个仓库到一个新目录 init 创建一个空的 Git 仓库或重新初始化一个已存在的仓库
  • 在当前变更上工作(参见:git help everyday) add 添加文件内容至索引 mv 移动或重命名一个文件、目录或符号链接 restore 恢复工作区文件 rm 从工作区和索引中删除文件
  • 检查历史和状态(参见:git help revisions) diff 显示提交之间、提交和工作区之间等的差异 log 显示提交日志 status 显示工作区状态
  • 扩展、标记和调校您的历史记录 branch 列出、创建或删除分支 commit 记录变更到仓库 merge 合并两个或更多开发历史 rebase 在另一个分支上重新应用提交 tag 创建、列出、删除或校验一个 GPG 签名的标签对象
  • 协同(参见:git help workflows) fetch 从另外一个仓库下载对象和引用 pull 获取并整合另外的仓库或一个本地分支 push 更新远程引用和相关的对象

在团队中使用Git进行协作

协作

接下来通过一个简单的例子展示Git协作。我们假设现在有一个远程仓库(/path/to/test-remote),Alice(alice@foo.com)和Bob(bob@foo.com)正通过Git进行协作。

同步远程仓库到本地

Alice想添加一个文件main.js,她已经在本地创建了一个仓库。Alice 首先将远程仓库添加到本地:

$ git remote add origin /path/to/test-remote

然后将远程仓库的内容同步到本地:

$ git pull origin main

修改并提交

Alice 新建了main.js文件,添加了一个函数,并提交到远程仓库:

+ (function main() {
+ 	let n = 1;
+ 	console.log(n);
+ })()
$ git add main.js
$ git commit -m "Add function main"
$ git push origin main

合并代码

在提交后,Alice继续添加了一个函数bar,并试图同步到远程仓库:

 (function main() {
 	let n = 1;
+ 	n = bar(n);
 	console.log(n);
 })()
+ function bar(n) {
+ 	return n * 3;
+ }

但是,Alice发现远程仓库已经被Bob修改了,Bob添加了一个函数foo,并提交到了远程仓库:

 (function main() {
 	let n = 1;
+ 	n = foo(n);
 	console.log(n);
 })()
+ function foo(n) {
+ 	return n * 2;
+ }

因此Alice需要将远程仓库的内容同步到本地,进行合并:

$ git pull origin main
(function main() {
	let n = 1;
<<<<<<< HEAD
	n = bar(n);
	console.log(n);
})()
function bar(n) {
	return n * 3;
=======
	n = foo(n);
	console.log(n);
})()
function foo(n) {
	return n * 2;
>>>>>>> 02aad896aede63ff7513f20ec9b74eeb544a1852
}

Alice发现,Git将两个函数合并到了一起,但是却添加了一些冲突标记,这是因为Git无法确定两个函数的先后顺序,因此需要Alice手动解决冲突。

Alice合并后,提交到远程仓库:

$ git add main.js
$ git commit -m "Merge branch 'main' of /path/to/test-remote"
$ git push origin main

以下是Git记录

git log.png

使用分支

在实际的协作开发中,通常不会直接将代码提交到远程仓库的主分支,而是在本地创建一个分支,进行开发,然后将分支合并到主分支,这样可以更加方便地管理代码。

可以使用以下命令创建一个分支:

$ git branch dev

然后切换到分支:

$ git checkout dev

或者使用以下命令创建并切换到分支:

$ git checkout -b dev

在分支上进行开发后,可以将分支合并到主分支:

$ git checkout main
$ git merge dev

Rebase

Rebase是另一种合并分支的方式,它可以将一个分支的修改合并到另一个分支中。与 git merge 不同,git rebase 可以将提交历史线性化,使得提交历史更加清晰。

具体来说,git rebase 可以将当前分支的修改“移动”到目标分支的最新提交之后,从而使得当前分支的修改基于目标分支的最新代码。

合并前:

%%{init: { 'theme': 'base'} }%%
gitGraph:
	commit	id:"init"
	commit	id:"commit1"
	branch fix
	commit	id:"fix sth"
	checkout main
	commit	id:"commit2"
	checkout fix
	commit	id:"fix sth2"

使用Merge合并分支后,提交历史如下:

%%{init: { 'theme': 'base'} }%%
gitGraph:
	commit	id:"init"
	commit	id:"commit1"
	branch fix
	commit	id:"fix sth"
	checkout main
	commit	id:"commit2"
	checkout fix
	commit	id:"fix sth2"
	checkout main
	merge fix id:"merge fix"

使用Rebase合并分支后,提交历史如下:

%%{init: { 'theme': 'base'} }%%
gitGraph:
	commit	id:"init"
	commit	id:"commit1"
	commit	id:"commit2"
	commit	id:"fix sth" type:HIGHLIGHT
	commit	id:"fix sth2" type:HIGHLIGHT

Rebase提供了清晰的提交历史的同时也影响了提交记录,可能会影响协作,也使得追踪更加困难。

Git的最佳实践

使用分支

当多个人在同一个代码库上工作时,使用分支是一种非常有用的方式来组织工作流程。每个人都可以在自己的分支上工作,这样就可以避免冲突和代码覆盖。

最佳实践

  • 主分支应该是稳定的,只包含已经经过测试的代码。
  • 开发人员应该在自己的分支上进行开发,而不是在主分支上进行。
  • 分支名称应该清晰明了,以便其他人可以轻松理解分支的目的。
  • 分支应该经常合并到主分支中,以确保代码的稳定性和一致性。
  • 使用 Pull Request 进行代码审查,以确保代码质量和一致性。
  • 避免在主分支上进行强制推送,以免破坏其他人的工作。

使用标签

当使用 Git 管理项目时,使用标签可以帮助我们更好地组织和管理代码库。

最佳实践

  • 使用语义化版本号作为标签名称,以便其他人可以轻松理解标签的含义。
  • 标签应该与提交相关联,以便可以轻松地找到特定版本的代码。
  • 使用轻量级标签(lightweight tag)来标记特定的提交,使用附注标签(annotated tag)来添加更多的信息,如版本号、发布日期、作者等。
  • 使用标签来标记重要的里程碑,如版本发布、重要功能的实现等。
  • 避免在标签上进行修改,以免破坏其他人的工作。

提交信息

提交信息是 Git 中非常重要的一部分,它可以帮助我们更好地理解代码库中的修改历史。

最佳实践

  • 提交信息应该清晰明了,以便其他人可以轻松理解修改的目的。
  • 提交信息应该包含修改的范围、原因和影响等信息。
  • 提交信息应该使用简洁的语言,避免使用过于复杂的术语和缩写。
  • 提交信息应该遵循一定的格式,如使用标题和正文等。格式可以参考如何规范你的Git commit?,但应该根据实际情况进行调整,避免信息过于冗长。

总结

本文介绍了 Git 的基本概念、在团队中使用 Git 进行协作、Git 的最佳实践等内容。在基本概念部分,介绍了 Git 是一种分布式版本控制系统,以及 Git 的基本概念和操作。在协作部分,介绍了如何同步远程仓库到本地、修改并提交、合并代码、使用分支和 Rebase 等内容。在 Git 的最佳实践部分,介绍了使用分支、使用标签和提交信息等内容。

在学习 Git 的过程中,我深刻认识到 Git 在团队协作中的重要性。Git 可以帮助团队成员更好地管理代码,协同开发,提高开发效率。在实际开发中,我们应该遵循 Git 的最佳实践,如使用语义化版本号作为标签名称、提交信息应该清晰明了等。同时,我们还应该注意 Git 的安全性,避免泄露代码库的敏感信息。此外,我们还应该不断学习 Git 的新特性和最佳实践,以便更好地应对日常开发中的挑战。