08 - Git 的正确使用姿势与最佳实践 | 青训营

56 阅读14分钟

Git 是一种分布式版本控制系统,它可以让多人在同一个项目上协作开发,同时保证代码的完整性和历史记录。Git 的使用姿势和最佳实践有很多,本文将介绍其中的一些重要的方面,包括:

  • Git 的基本概念和工作流程
  • Git 的常用命令和参数
  • Git 的分支管理和合并策略
  • Git 的远程仓库和协作模式
  • Git 的冲突解决和撤销操作
  • Git 的高级功能和扩展工具

Git 的基本概念和工作流程

Git 是基于快照的版本控制系统,它会在每次提交(commit)时,记录下文件的状态和变化。Git 有三种主要的状态,分别是:

  • 工作区(working directory):这是你正在编辑的文件所在的地方,它们可能是已经被 Git 跟踪(tracked)的,也可能是还没有被 Git 跟踪(untracked)的。
  • 暂存区(staging area):这是你准备提交的文件所在的地方,你可以通过 git add 命令将工作区中的文件添加到暂存区,也可以通过 git restore --staged 命令将暂存区中的文件移回工作区。
  • 仓库(repository):这是你已经提交的文件所在的地方,它们被保存在 .git 目录中,你可以通过 git commit 命令将暂存区中的文件提交到仓库,也可以通过 git checkout 命令将仓库中的文件恢复到工作区。

Git 的基本工作流程如下:

  1. 在工作区中修改文件。
  2. 将修改后的文件添加到暂存区。
  3. 将暂存区中的文件提交到仓库。
  4. 如果需要,将仓库中的文件推送(push)到远程仓库或从远程仓库拉取(pull)文件到本地仓库。

Git 的常用命令和参数

Git 有很多命令和参数,可以实现各种功能。这里列举一些常用的命令和参数,并给出简单的说明和示例。

  • git init:初始化一个空的 Git 仓库或重新初始化一个已有的 Git 仓库。例如,git init 会在当前目录下创建一个 .git 目录,如果已经存在一个 .git 目录,则不会覆盖它。
  • git clone:克隆一个远程仓库到本地。例如,git clone https://github.com/user/repo.git 会将 https://github.com/user/repo.git 这个远程仓库克隆到当前目录下,并创建一个名为 repo 的子目录。
  • git status:查看工作区、暂存区和仓库之间的状态差异。例如,git status 会显示哪些文件被修改了、哪些文件被添加了、哪些文件被删除了等等。
  • git add:将工作区中的文件添加到暂存区。例如,git add . 会将当前目录下的所有文件添加到暂存区,git add file.txt 会将 file.txt 这个文件添加到暂存区。
  • git commit:将暂存区中的文件提交到仓库。例如,git commit -m "message" 会将暂存区中的文件提交到仓库,并附上一条消息 "message" 作为提交说明。如果不加 -m 参数,则会打开一个编辑器让你输入提交说明。
  • git log:查看仓库中的提交历史。例如,git log 会显示仓库中的所有提交,包括提交的哈希值、作者、日期和说明,git log --oneline 会以一行的形式显示每个提交,只包括提交的哈希值和说明。
  • git diff:查看工作区、暂存区和仓库之间的内容差异。例如,git diff 会显示工作区和暂存区之间的差异,git diff --staged 会显示暂存区和仓库之间的差异,git diff HEAD 会显示工作区和仓库之间的差异。
  • git checkout:切换分支或恢复文件。例如,git checkout master 会切换到 master 这个分支,git checkout file.txt 会将 file.txt 这个文件恢复到最近一次提交的状态。
  • git branch:查看或创建分支。例如,git branch 会显示当前仓库中的所有分支,并用一个星号标记当前所在的分支,git branch dev 会创建一个名为 dev 的分支。
  • git merge:合并两个分支。例如,假设当前在 master 分支上,执行 git merge dev 会将 dev 分支上的修改合并到 master 分支上。如果没有冲突,则会自动创建一个合并提交,如果有冲突,则需要手动解决冲突后再提交。
  • git push:将本地仓库中的修改推送到远程仓库。例如,假设当前在 master 分支上,执行 git push origin master 会将本地仓库中的 master 分支上的修改推送到名为 origin 的远程仓库中的 master 分支上。如果远程仓库中没有对应的分支,则会自动创建一个。
  • git pull:将远程仓库中的修改拉取到本地仓库。例如,假设当前在 master 分支上,执行 git pull origin master 会将名为 origin 的远程仓库中的 master 分支上的修改拉取到本地仓库中的 master 分支上,并自动合并。如果有冲突,则需要手动解决冲突后再提交。

这些命令和参数只是 Git 的一部分功能,还有很多其他的命令和参数可以实现更多的功能,可以通过 git help <command> 或者查看 [Git 文档] 来了解更多。

Git 的分支管理和合并策略

Git 的一个强大之处在于它可以创建多个分支,并在不同的分支上进行不同的开发任务。分支可以让你在不影响主要代码的情况下进行实验性或者功能性的修改,也可以让你在不同的时间点或者不同的场景下切换到不同的代码状态。

Git 的默认分支是 master,它通常代表了项目的稳定版本。除了 master 分支外,你还可以创建其他的分支来进行开发工作,例如:

  • 创建一个名为 dev 的分支来进行日常开发工作,并定期将其合并到 master
  • 创建一个名为 feature-x 的分支来开发一个新功能,并在完成后将其合并到 dev
  • 创建一个名为 hotfix-y 的分支来修复一个紧急 bug,并在修复后将其合并到 master

Git 的分支管理是基于指针(pointer)的。每个分支都是一个指针,指向某个提交(commit)。当你在某个分支上进行提交时,那么这个分支的指针就会向前移动,指向新的提交。当你切换分支时,Git 会根据分支的指针来更新工作区和暂存区的内容,让你看到对应分支的文件状态。

Git 的分支合并是基于快照(snapshot)的。当你合并两个分支时,Git 会比较两个分支的最新提交(即分支指针所指向的提交),以及它们的最近共同祖先(即两个分支最后一次分叉的地方),然后根据这三个快照来创建一个新的快照,作为合并的结果。

Git 的合并策略有两种,分别是:

  • 快进(fast-forward)合并:这是一种简单的合并方式,当你要合并的两个分支没有分叉,即一个分支是另一个分支的直接后继时,Git 只需要将目标分支的指针移动到源分支的指针所在的位置,就完成了合并。这种合并方式不会创建新的提交,也不会改变历史记录。
  • 三方(three-way)合并:这是一种复杂的合并方式,当你要合并的两个分支有分叉,即两个分支都有各自独立的修改时,Git 需要将两个分支的最新提交和最近共同祖先进行比较,找出它们之间的差异,并尝试将这些差异合并到一个新的提交中,作为合并的结果。这种合并方式会创建新的提交,并且会改变历史记录。

Git 的合并可能会遇到冲突(conflict),即两个分支对同一个文件或同一行代码做了不同的修改,导致 Git 无法自动决定应该采用哪个版本。当发生冲突时,Git 会在合并后的文件中用特殊的标记来显示冲突的位置,例如:

<<<<<<< HEAD
This is the version from the current branch.
=======
This is the version from the other branch.
>>>>>>> other-branch

你需要手动编辑这些文件,选择或者整合你想要保留的版本,并删除 Git 添加的标记。然后你需要将这些文件重新添加到暂存区,并完成合并提交。

Git 的远程仓库和协作模式

Git 是一种分布式版本控制系统,它允许你将本地仓库与远程仓库进行连接和交互。远程仓库是一个存储在网络上的 Git 仓库,它可以让你与其他人共享和协作开发项目。

Git 的远程仓库有很多种形式,例如:

  • 一个托管在 GitHub、GitLab、Bitbucket 等平台上的公开或者私有仓库
  • 一个部署在自己或者第三方服务器上的裸(bare)仓库
  • 一个通过 SSH、HTTP、FTP 等协议访问的本地文件系统上的仓库

你可以通过 git remote 命令来管理你本地仓库与远程仓库之间的关联。例如:

  • git remote add origin https://github.com/user/repo.git:将本地仓库与名为 origin 的远程仓库关联起来,远程仓库的地址是 https://github.com/user/repo.git
  • git remote -v:查看本地仓库与远程仓库之间的关联情况,包括每个远程仓库的名称和地址
  • git remote remove origin:取消本地仓库与名为 origin 的远程仓库之间的关联

你可以通过 git pushgit pull 命令来与远程仓库进行数据交换。例如:

  • git push origin master:将本地仓库中的 master 分支上的修改推送到名为 origin 的远程仓库中的 master 分支上
  • git pull origin master:将名为 origin 的远程仓库中的 master 分支上的修改拉取到本地仓库中的 master 分支上,并自动合并

Git 的协作模式有很多种,例如:

  • 集中式协作模式:这是一种简单的协作模式,所有的开发者都使用同一个远程仓库作为中心,每个开发者都可以直接从远程仓库拉取或者推送数据,不需要经过任何审核或者授权。这种协作模式适合小型或者信任度高的团队,但是也容易造成冲突或者覆盖。
  • 分布式协作模式:这是一种复杂的协作模式,每个开发者都有自己的远程仓库,每个开发者都可以从其他开发者的远程仓库拉取或者推送数据,但是需要经过一定的审核或者授权。这种协作模式适合大型或者信任度低的团队,但是也需要更多的沟通和协调。
  • 拉取请求(pull request)协作模式:这是一种常用的协作模式,它结合了集中式和分布式的优点,每个开发者都使用同一个远程仓库作为中心,但是每个开发者都在自己的分支上进行开发工作,当开发者完成一个功能或者修复一个 bug 时,他们可以向远程仓库发送一个拉取请求(pull request),请求将自己的分支合并到主分支上。这样,其他开发者可以对这个拉取请求进行查看、评论、测试、修改或者批准。这种协作模式可以保证代码的质量和一致性,也可以增加代码的可追溯性和可维护性。

Git 的冲突解决和撤销操作

Git 的冲突解决和撤销操作是两种常见的应对错误或者问题的方法。当你在使用 Git 时遇到了冲突或者错误时,你可以通过以下方式来解决或者撤销:

  • 冲突解决:当你在合并两个分支时遇到了冲突时,你需要手动编辑冲突文件,并选择或者整合你想要保留的版本,并删除 Git 添加的标记。然后你需要将这些文件重新添加到暂存区,并完成合并提交。你也可以使用一些图形化的工具来帮助你解决冲突,例如 [SourceTree]、[TortoiseGit] 等。

  • 撤销操作:当你在提交、合并、推送等操作时犯了错误时,你可以使用一些命令来撤销你的操作,例如:

    • git reset:将暂存区或者仓库重置到某个状态。例如,git reset --hard HEAD^ 会将暂存区和仓库重置到上一个提交(HEAD^)的状态,并且丢弃当前提交(HEAD)及其之后的所有修改。
    • git revert:创建一个新的提交来撤销某个提交。例如,git revert HEAD 会创建一个新的提交(HEAD+1),它与当前提交(HEAD)相反,即它会取消当前提交所做的所有修改。
    • git restore:恢复工作区或者暂存区中的文件到某个状态。例如,git restore file.txt 会将 file.txt这个文件恢复到最近一次提交的状态,git restore --staged file.txt 会将 file.txt 这个文件从暂存区移回到工作区。

这些命令和参数只是 Git 的一部分功能,还有很多其他的命令和参数可以实现更多的功能,可以通过 git help <command> 或者查看 [Git 文档] 来了解更多。

Git 的高级功能和扩展工具

Git 还有一些高级功能和扩展工具,可以让你更方便、更高效、更安全地使用 Git。这里列举一些常用的功能和工具,并给出简单的说明和示例。

  • Git 的配置(config):你可以通过 git config 命令来配置 Git 的行为和属性。例如,你可以设置你的用户名和邮箱,这些信息会被用于创建提交时的作者信息,你可以通过 git config --global user.name "your name"git config --global user.email "your email" 来设置。你也可以设置你的编辑器、合并工具、别名(alias)等等,这些信息会被保存在 .gitconfig 文件中,你可以通过 git config --list 来查看。
  • Git 的钩子(hook):你可以通过在 .git/hooks 目录下创建一些脚本文件来自定义 Git 的行为。例如,你可以创建一个名为 pre-commit 的脚本文件,它会在每次提交前执行,你可以在这个脚本中检查代码的格式、风格、错误等等,如果不符合要求,则拒绝提交。你也可以创建其他的钩子,例如 post-commitpre-pushpost-receive 等等,来实现不同的功能。
  • Git 的子模块(submodule):你可以通过 git submodule 命令来管理你的项目中包含的其他项目。例如,如果你的项目依赖于另一个项目,你可以将那个项目作为一个子模块添加到你的项目中,这样你就可以方便地跟踪和更新那个项目的状态。你也可以将子模块添加到远程仓库中,这样其他人也可以获取到子模块的信息。
  • Git 的标签(tag):你可以通过 git tag 命令来给你的仓库中的某个提交打上一个标签,以便于识别和引用。例如,如果你要发布一个版本,你可以给那个版本对应的提交打上一个标签,例如 v1.0.0,这样你就可以方便地切换到那个版本或者从那个版本创建分支。你也可以将标签推送到远程仓库中,这样其他人也可以看到标签的信息。
  • Git 的补丁(patch):你可以通过 git format-patch 命令来创建一个补丁文件,它包含了某个提交或者某个范围内的提交所做的修改。例如,如果你要将你的修改发送给其他人进行审查或者应用,但是又不想使用拉取请求或者推送操作,你可以创建一个补丁文件,并通过邮件或者其他方式发送给他们。他们可以通过 git apply 命令来应用这个补丁文件,并看到修改的效果。

如果你想了解更多关于 Git 的知识和技巧,请参考以下资源:

  • [Git 文档]:Git 官方文档,包含了 Git 的基本介绍、教程、参考手册、书籍等内容。
  • [Pro Git]:一本关于 Git 的经典书籍,由 Scott Chacon 和 Ben Straub 编写,涵盖了 Git 的各个方面,适合初学者和高级用户。
  • [Git 教程]:一个由廖雪峰编写的 Git 教程,用通俗易懂的语言和丰富的示例,介绍了 Git 的基本用法和高级技巧。
  • [Git Magic]:一个由 Ben Lynn 编写的 Git 指南,用幽默风趣的语言和有趣的比喻,讲解了 Git 的原理和实践。