Git 命令速查表

前言
Git 是一个 分布式版本控制系统 ,主要用于跟踪溯源文件的版本。开发人员常常使用 Git 来做项目的源代码版本控制。Git 最初的设计目标包括快速、数据完整、分布式、非线性工作流(例如在不同计算机上运行数千个并行分支),它是一款免费的开源软件,可在 GPL-2.0 许可下共享。
与绝大多数的分布式版本控制系统一样,它与 客户端-服务器系统 不同。Git 可以维护整个 存储仓库(Repository, 也称为 repo)的本地副本,拥有历史记录和版本跟踪功能,同时可以脱机(无网络)或者脱离中央服务器。 存储仓库 会在每一台计算机的目录中,并带有额外的隐藏配置、记录文件来提供版本控制。Git 可以在两个共享历史记录的仓库之间同步更改、克隆。对于多人合作,Git 可以与远程计算机进行仓库同步等操作。虽然每台计算机的 存储仓库 (具有相同的历史记录)都是对等的,但开发人员通常使用一个中央服务器来作为远程仓库托管,来保存集成副本。

Git 最初是由 Linus Torvalds 创建的,刚开始仅仅是用于在 Linux 内核开发中进行版本控制。 Git 这个商标则是由软件自由保护协会注册,标志着 Git 在开源社区中得到官方的认可和持续的发展潜力。如今, Git 已然成为版本控制系统的事实标准。他是最受欢迎的分布式版本控制系统,截至 2022 年,几乎近 95% 的开发人员将其作为首要的版本控制系统。他是专业的开发人员中最广泛使用的源代码管理工具。
历史
2005 年 4 月份,在 Linux 的 BitKeeper (一款源代码管理工具,自 2002 年来用于 Linux 开发) 免费许可证被撤销后,Torvalds 开始开发 Git。 BitKeeper 的版权持有者 Larry McVoy 声称 Andrew Tridgell 通过对 BitKeeper 协议进行逆向开发,创建了 SourcePuller 。这一事件也促使了同期的另一个版本控制系统 Mercurial 的诞生。
此时的 Torvalds 想要一个与 BitKeeper 相似的分布式系统,但是那时的市面上并没有任何一个免费版的系统能符合他的需求。他举了一个例子,一个源代码管理系统需要 30s 才能打上补丁并更新所有相关的元数据,并且他指出这无法满足 Linux 内核开发的需求,因为与其他的维护人员同步可能需要同时执行 250 次这样的操作。而在他的设计标准里,他明确地指出修补时间应不超过 3s ,并且添加了一下三个目标:
- 以并发版本系统(CVS)为例,说明哪些操作不该做;如有疑问,请做出完全相反的决定。
- 支持类似 BitKeeper 这样的分布式工作流程。
- 包含强大的安全保护措施,以防止意外或恶意损坏。
意料之中的,这些标准淘汰了当时所有的版本控制系统,所以 Torvalds 在 Linux 内核 2.6.12-rc2 开发版本发布以后立刻着手开发了自己的版本控制系统。
Git 的开发正式启动于 2005 年 4 月 3 日。 Torvalds 于同年的 4 月 6 日宣布了该项目,并在次日实现了自托管。 4 月 18 日完成了多分支的首次合并。 Torvalds 实现了他的性能目标; 4 月 29 日,新型的 Git 进行了基准测试,以每秒 6.7 个补丁的速度向 Linux 内核树记录补丁。 6 月 16 日, Git 管理了内核 2.6.12 版本。
Torvalds 于 2005 年 7 月 26 日将维护工作移交给了该项目的主要贡献者 Junio Hamano 。 Hamano 负责了 2005 年 12 月 21 日的 1.0 版本发布。
关于命名
Torvalds 曾讽刺地调侃过 git 这个名字(在英式英语的俚语中意为“令人讨厌的人”):“我是个自负的混蛋,我所有的项目都是我自己命名。起初是 ‘Linux’ ,现在是 ‘git’ 。 Git 的帮助手册将其描述为“愚蠢的目录追踪器”。
源代码中的 ReadMe 文件对此有更进一步的阐述:
1 | - "git" can mean anything, depending on your mood. |
Git 的源代码将该程序称之为“来自地狱的信息管理器”。
了解 Git
我们从经典源代码存储库中的一个基本示例开始,如图 1 所示。在经典源代码存储库中,包含文件和子文件夹的文件夹将作为内容进行处理( CVS 和 Git 实际上不处理文件夹,仅处理路径位置)。存储库保存内容的所有版本,而工作目录是修改代码的位置。正常的操作是将代码从存储库检出到工作目录,并将在此工作目录中所作的更改提交会存储库中内容的新版本。

每次提交都会创建一个新的内容子版本,该内容派生自先前修改的父版本,如图 2 所示。内容存储为一系列版本(也成为快照),通过创建的父子关系链接提交操作。通过提交在父版本和子版本之间发生更改的信息称为更改集。这一系列的版本成为流或分支。在 SVN 中,主流称为 trunk ;在 CVS 中,它通常称为 HEAD ;在 Git 中,一般命名为 master 。分支在实施项目中用于分离特定功能的开发或用于旧版本的维护。

到目前为止, Git 真的与经典源代码存储库工具很相似,但相似之处也就到此为止了。 CVS 和 SVN 的一大特点是它们有一个中央存储库。 Git 是去中心化的,多个存储库可以在软件开发中协同工作,每个开发人员的工作和通信方式与任何基于服务器的 Git 存储库相同。
Git 的工作原理
一旦理解了 Git 的主要原理,就会发现它非常简单。
首先, Git 处理快照中的内容,每次提交一个快照,并且
工作流程
如下是基本的工作流程:

1. 克隆仓库
如果你要参与一个已有的项目,首先需要将远程仓库克隆到本地:
1 | git clone http://github.com/username/repo.git |
2. 创建新分支
为了避免直接在 main 或 master 分支上进行开发,通常会创建一个新的分支,用来在本地进行开发。
1 | git checkout -b new-feature |
3. 开发、增删改查
利用各种 IDE 进行代码开发、添加或删除不必要的文件。
4. 暂存文件
将修改过的文件添加到暂存区,以便进行下一步的操作:
1 | git add filename |
5. 提交更改
将暂存区的更改提交到本地的仓库,并添加提交信息:
1 | git commit -m "Add new feature" |
6. 拉取最新更改
在推送本地更改之前,最好先从远程仓库拉取最新的更改,以避免冲突:
1 | git pull origin main/master |
7. 推送更改
将本地的提交推送到远程仓库:
1 | git push origin new-feature |
8. 创建 Pull Request(PR)
在 Github 或其他托管平台上创建 Pull Request ,邀请团队成员进行代码审查。 PR 合并后,你的更改就会合并到主分支。
9. 合并更改
在 PR 审核通过合并后,可以将远程仓库的主分支合并到本地分支:
1 | git checkout main |
10. 删除分支
如果不再需要新功能分支,可以将其删除:
1 | git branch -d new-feature |
或者从远程仓库删除分支:
1 | git push origin --delete new-feature |
Git 工作区、暂存区和版本库
- 工作区: 即本地电脑能看到的目录。
- 暂存区: 英文叫 stage 或 index 。一般存放在 .git 目录下的 index 文件中,所以暂存区有时也叫做索引(Index)
- 版本库: 工作区有一个隐藏目录 .git ,这个不算工作区,而是 Git 的版本库。

1. 工作区
工作区是本地的项目目录,可以在目录中进行文件的创建、修改和删除操作。工作区包含了当前项目的所有文件和子目录。
特点:
- 显示项目的当前状态。
- 文件的修改在工作区中进行,但这些修改还没有被记录到版本控制中。
2. 暂存区
暂存区是一个临时存储区域,它包含了即将被提交到版本库中的文件快照,在提交之前,你可以选择性地将工作区中的修改添加到暂存区。
特点:
- 暂存区保存了将被包括在下一个提交中的更改。
- 你可以多次使用 git add 命令来将文件添加到暂存区,直到你准备好提交所有更改。
常用命令:
1 | git add filename # 将单个文件添加到暂存区 |
3. 版本库
版本库包含项目的所有历史版本记录。
每次提交都会在版本库中创建一个新的快照,这些快照是不可变的,确保了项目的完整历史记录。
特点:
- 版本库分为本地版本库和远程版本库。这里主要指本地版本库。
- 本地版本库存储在 .git 目录中,它包含了所有提交的对象和引用。
常用命令:
1 | - git commit -m "Commit message" # 将暂存区的更改提交到本地版本库 |
子仓库
- 创建:
当我们的项目伴随着时间的增长越来越大的时候,单一的仓库便不再方便管理,这时候就需要将部分功能提取出来单一作为一个仓库管理,这时候就会出现仓库里面包含仓库的情况。这时候就需要 git submodule
添加子仓库。
1 | git submodule add https://github.com/#yourname#/#repositoryname#.git path |
注意: 添加完子仓库后,一定记得先 commit
提交保存后,在进行其他操作,养成保存的良好习惯。
- 删除:
- 进入包含子模块的父仓库根目录。
- 使用命令
git submodule deinit 子仓库路径
,将子仓库从父仓库的配置中删除。 - 使用命令
git rm 子仓库路径
,删除子仓库所有文件。 - 进入 .git/module ,删除相关仓库文件夹。
- 提交修改,使用命令
git commit -m “备注"
。
多人协作
对于非仓库管理者而言,因为没有任何的权限,无法进行 push
操作,首先需要将项目克隆至本地,这样可以获取代码并在本地进行修改,修改完后需要进行 pull request
操作请求仓库管理者进行代码合并。
什么是 fork ?
fork
即在自己的 GitHub 账户中创建一个原始仓库的副本,该操作会使得副本仓库包含原始仓库的所有代码和历史记录,此时能够在副本中独立进行修改和开发,且不影响原始仓库。如果你想要将你的修改合并到原始仓库中,可以向原始仓库提交 “Pull Request(拉取请求)”,请求将你的修改该合并到原始仓库,待仓库管理员同意后即可合并。这是一种多人协作方式,常见于开源项目的贡献和团队合作。
什么是 Pull Request ?
Pull Request 是协作机制,常用于开源项目或团队协作中。此操作是将自己的修改提交到项目的管理者,请求将这些修改合并到原始仓库中。Pull Request 一般会伴随着 fork
同时使用。
引言
到目前为止,当今世界上使用最广泛的现代版本控制系统是 Git 。 Git 是一个成熟的、积极维护的开源项目,最初由 Linux 操作系统内核的著名创建者 Linus Torvalds 于 2005 年开发。有海量软件项目依赖 Git 进行版本控制,包括商业项目和开源项目。使用过 Git 的开发人员在可用的软件开发人才库中占有很好的比例,它在各种操作系统和 IDE(集成开发环境)上都能很好地运行。
Git 采用分布式架构,是 DVCS(分布式版本控制系统)的示例。在 Git 中,每个开发人员的代码工作副本也是一个可以包含所有变更完整历史记录的存储库,而不是像曾经流行的 CVS 或 Subversion(也称为 SVN )等版本控制系统那样,只有一个地方存放软件的完整版本历史记录。
除了分布式外, Git 的设计还考虑了性能、安全性和灵活性。
什么是版本控制?
-
版本控制,也称为源代码控制,是一种跟踪和管理软件代码变更的实践。版本控制系统是软件工具,可帮助软件团队管理源代码随时间推移而发生的变更。随着开发环境的加速,版本控制系统可以帮助软件团队更快、更智能地工作。
-
版本控制软件在特殊类型的数据库中跟踪对代码的每一次修改。如果犯了错误,开发人员可以回退并比较代码的早期版本,以帮助修复错误,同时最大限度地减少对所有团队成员的干扰。
-
版本控制可以跟踪每个贡献者的每一个单独变更,并帮助防止并行工作发生冲突。对软件某一部分所做的变更可能与同时工作的另一位开发人员所做的变更不兼容。应该在不妨碍团队其他成员工作的情况下有序地发现和解决这个问题。此外,在所有软件开发中,任何变更都可能自行引入新的错误,新软件在经过测试之前是不可信的。因此,测试和开发将一起进行,直到新版本准备就绪。
关于源代码管理
-
源代码管理 (SCM) 用于跟踪对源代码存储库的修改。 SCM 跟踪代码库变更的运行历史记录,并帮助解决合并来自多个贡献者的更新时发生的冲突。 SCM 也是版本控制的代名词。
-
随着软件项目代码行数和贡献者人数的增加,通信开销和管理复杂性的成本也在增加。 SCM 是缓解不断增长的开发成本带来的组织压力的关键工具。
那么, Git 是什么呢?
为什么使用 Git ?
从集中式版本控制系统切换到 Git 会改变开发团队创建软件的方式。而且,如果您是一家依赖其软件来开发任务关键型应用的公司,那么改变您的开发工作流程会影响你的整个业务。
功能分支工作流
Git 的最大优势之一是其分支功能。与集中式版本控制系统不同, Git 分支便宜且易于合并。这简化了受许多 Git 用户欢迎的功能分支工作流程。
功能分支为代码库的每次变更提供了一个隔离的环境。当开发人员想要开始做某件事时(无论大小),他们都会创建一个新分支。这样可以确保主分支始终包含生产质量的代码。
使用功能分支不仅比直接编辑生产代码更可靠,而且还能为组织带来好处。它们允许您以与敏捷待办事项列表相同的精度呈现开发工作。
分布式开发
在 SVN 中,每个开发人员都会获得一个指向单个中央存储库的工作副本。但是, Git 是一个分布式版本控制系统。不是工作副本,而是每个开发人员都有自己的本地存储库,里面有完整的提交历史记录。
拥有完整的本地历史记录可以让 Git 变得更快,因为这意味着您不需要网络连接即可创建提交、检查文件的先前版本或在提交之间执行比对。
分布式开发还可以更轻松地扩展您的工程团队。如果有人破坏了 SVN 中的生产分支,则其他开发人员在修复之前无法添加变更。对于 Git 来说,这种障碍是不存在的。每个人都可以继续在自己的本地存储库中作业。
而且,与功能分支类似,分布式开发创造了更可靠的环境。即使开发者删除了自己的存储库,他们也可以简单地克隆别人的存储库然后重新开始。
拉取请求
拉取请求是一种要求其他开发人员将您的一个分支合并到他们存储库中的方式。这不仅使项目主管更容易跟踪变更,还可以让开发人员在将其与代码库其余部分集成之前围绕他们的工作展开讨论。
由于它们本质上是附加到功能分支的评论话题,因此拉取请求的用途非常广泛。当开发人员遇到棘手问题时,他们可以提出拉取请求,向团队其他成员寻求帮助。或者,初级开发人员可以通过将拉取请求视为正式的代码审查来确信他们不会破坏整个项目。
社区
在许多圈子里,Git 已成为新项目的预期版本控制系统。如果您的团队正在使用 Git,您很可能不必对新员工进行工作流程培训,因为他们已经熟悉了分布式开发。
此外,Git 在开源项目中非常受欢迎。这意味着可以轻松利用第三方库并鼓励其他人克隆您自己的开源代码。
更快的发布周期
功能分支、分布式开发、拉取请求和稳定社区的最终结果是更快的发布周期。这些功能促进了敏捷的工作流程,鼓励开发人员更频繁地共享较小的变更。反过来,与集中式版本控制系统常见的单一版本相比,变更可以更快地推送到部署管道中。
正如您所预料的那样, Git 在持续集成和持续交付环境中运行得很好。 Git 钩子允许您在存储库内发生某些事件时运行脚本,这使您可以自动部署到您想要的内容。您甚至可以从特定分支构建代码或将代码部署到不同的服务器。
例如,您可能需要配置 Git ,以便在有人将拉取请求合并到测试服务器时,将最新的提交从开发分支部署到测试服务器。将这种构建自动化与同行评审相结合,意味着在代码从开发到暂存再到生产的过程中,您可以极大地放心。