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 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 的新特性和最佳实践,以便更好地应对日常开发中的挑战。