版本控制器Git(2)
文章目录
- 前言
- 一、Git版本回退
- git reset
- Git 版本回退速度及原理
- 二、撤销修改
- 情况一:对于工作区的代码,还没有 add
- 情况二:已经 add,但没有 commit
- 情况三:已经 add,并且也 commit
- 删除文件
- 三、分支管理
- 理解分支
- 创建与管理分支
- 合并分支
- 删除分支
- 合并冲突
- 查看分支合并情况
- 分支管理策略
- 总结
前言
承上启下,开始新的一篇!
一、Git版本回退
git reset
Git 提供了强大的版本回退功能,允许开发者在发现当前工作存在重大问题时,能够快速地回到某个特定的历史版本重新开始。这不仅提高了开发效率,还保障了代码的质量和稳定性。
git reset 是用于回退版本的主要命令,它可以根据不同的参数选择性地回退工作区、暂存区或版本库的内容。其语法格式如下:
- –soft:仅回退版本库 (commit 后的) 到指定版本,工作区和暂存区内容保持不变。
- –mixed(默认):回退暂存区到指定版本 index,工作区文件保持不变。可以继续编辑这些文件。
- –hard:将暂存区和工作区都回退到指定版本。注意:此操作会丢失工作区中未提交的更改,请谨慎使用。
git reset [--soft | --mixed | --hard] [commit]
指定回退版本的方式
- 直接写 commit id:精确指定要回退到的提交记录。
- HEAD:表示当前版本。
- HEAD^ 或 HEAD~1:表示上一个版本。
- HEAD^^ 或 HEAD~2:表示上上一个版本,以此类推。
为了演示这种版本回退,我们现在提交了三个不同版本的 ReadMe
现在我们查看历史提交记录:
现在假设我们在提交完 version3 后,发现编写错误,想回退到 version2,并基于 version2 重新开始编写(也就是说工作区也回退到 version2 )。此时我们需要使用 --hard 参数来确保工作区的内容也回退到 version2:
验证回退成功~
如果之后又后悔想要回到 version3,可以通过 git reflog 查找之前的提交记录,找到 version3 的 commit id 并执行回退:
此时又变回 version3 版本了!
Git 版本回退速度及原理
Git 的版本回退速度非常快,这得益于其内部机制。Git 在每个分支(例如 master)上维护一个指向当前提交的 HEAD 指针。具体来说:
- refs/heads/master 文件:保存了当前 master 分支的最新 commit id。
- 回退版本时的操作:Git 实际上只是更新 refs/heads/master 中存储的 commit id,使其指向特定的历史版本。
这种设计使得 Git 可以迅速完成版本回退,而无需对整个项目进行重新构建或处理大量数据。
二、撤销修改
当我们在工作区编写了一段时间后,如果觉得代码质量不高,想要恢复到最近一次 add 或 commit 的状态,可以使用以下几种方法:
情况一:对于工作区的代码,还没有 add
- 直接删除新增代码:如果你只修改了少量内容,可以直接编辑文件删除不需要的部分。
- 使用 git checkout – [file] 命令:更推荐的方式是使用此命令来恢复文件到最近一次 add 或 commit 的状态。注意命令中的 – 参数非常重要,不可省略。
情况二:已经 add,但没有 commit
当你已经将更改添加到了暂存区,但尚未提交时,可以通过 git reset 命令撤消暂存区的内容,并选择是否保留工作区的更改。
情况三:已经 add,并且也 commit
-
本地回退:如果更改还未推送到远程仓库,可以安全地使用 git reset --hard HEAD^ 回退到上一个版本。请注意,–hard 参数会同时影响工作区和暂存区,请谨慎使用。
-
远程回退:一旦推送至远程仓库,建议不要轻易回退,因为这可能会影响到其他开发者的工作。此时应该考虑创建新的提交来修正问题,而不是直接回退历史记录。
删除文件
在 Git 中,删除文件也是一个修改操作。直接删除文件不会自动同步到版本库,因此需要额外的步骤来确保变更被正确记录。
但是如果是我们误删了文件,可以使用 git checkout – [file] 来恢复文件
三、分支管理
理解分支
Git 的杀手级功能之一是分支。通过分支,Git 允许用户在不影响主代码库的情况下探索新的想法或修复错误。这就好比在一个武侠故事中,你能够使用分身术来同时学习不同的武艺,最后将所有技能合为一体以获得竞争优势。
- 主线(master主分支):当你初始化一个Git仓库时,默认会创建一个名为 master 的主分支。这个分支可以被视为项目的主要发展线,所有最新的稳定版本都存于此。
- HEAD指针:它是一个指向当前分支的指针,默认情况下指向 master 分支。HEAD的作用在于标识当前工作的分支,并且可以灵活地指向任何分支。
- 每次提交,master分⽀都会向前移动⼀步,这样,随着你不断提交,master分⽀的线也越来越⻓,⽽
HEAD只要⼀直指向master分⽀即可指向当前分⽀
创建与管理分支
为了更有效地开发和测试新功能,我们可以从主分支创建新的分支,进行独立的工作,然后在适当的时候合并回主分支。
查看本地分支:
- 使用命令 git branch 可以列出所有的本地分支。带有星号(*)标记的分支表示当前正在工作的分支。
创建新分支:
- 使用命令 git branch [分支名] 来创建一个新的分支。需要注意的是,创建新分支并不会自动切换到该分支下工作,新分支的起始点为当前分支的最新提交。
切换分支:
- 若要开始在新创建的分支上工作,需要将HEAD指针移动到目标分支,可以通过命令 git checkout [分支名] 实现。此操作后,你在该分支上的所有改动都将被追踪并记录在此分支的历史中。
在dev下提交文件并切换回主分支:
- 当我们切回到 master 分支时,发现之前在dev分支上创建的 test.txt 好像“消失了”。这是因为我们在 dev 分支进行了新的提交,但这些改动尚未合并到 master 分支。
查看提交历史:
- 通过检查 dev 分支的最新提交ID,并打印其前一个提交ID,我们发现它正好是创建 dev 分支时 master 分支的最新提交ID。这表明我们在 dev 分支上进行了额外的提交,因此 dev 指向了更新的提交记录,而 master 保持不变。
合并分支
合并准备:如果想要在 master 分支看到 dev 分支上的新增代码,我们需要将两个分支进行合并。为此,必须先切换到 master 分支,然后执行合并命令。
合并命令:git merge [分支名]:用于合并指定分支到当前分支。
Fast-forward模式:当执行合并时,Git可能采用快进(Fast-forward)模式直接将 master 分支指针移动到 dev 分支的最新提交位置,因为从 master 到 dev 的路径上没有分叉。这使得合并过程非常快速且简单。
结果验证:合并完成后,可以在 master 分支上查看 test 文件,确认新增的一行代码已经成功加入。
合并后master分支和dev分支一样指向最新提交的commit id
删除分支
删除条件:一旦完成任务并且合并了分支,原分支(如 dev)就不再需要,可以安全地删除。
删除命令:git branch -d [分支名]:用于删除本地分支。需要注意的是,你不能删除当前所在的分支,也不能删除未完全合并的分支,除非使用 -D 强制删除。
最佳实践:由于创建、合并和删除分支的操作非常快捷,Git鼓励为每个任务创建独立的分支,完成后立即合并 并删除,以保持工作流的安全性和整洁性。
合并冲突
在实际开发中,不同分支可能对同一文件进行了不同的修改,导致合并时出现冲突。例如,dev1 和 master 分支都修改了 test 文件中的同一行。
此时仓库状态:
然后我们让master merge dev分支,两个分支 两次 commit 的内容就会发生冲突
合并 test 文件冲突,我们需要手动解决冲突然后将结果在进行提交。
- 解决冲突:Git会标记出冲突区域,用特殊符号(如 <<<<<<<, =======, >>>>>>>)来区分不同分支的修改内容。开发人员需要手动决定保留哪一部分或如何整合这两部分代码。
- 合并后提交:解决冲突后,需要再次提交更改,以完成合并过程。这是非常重要的一步,确保所有更改都被正确记录下来,此时提交线如下图所示。
查看分支合并情况
带参数的git log命令:git log --graph --pretty=oneline --abbrev-commit:这个命令可以图形化地显示提交历史,包括分支的合并情况,帮助更好地理解项目的历史发展。
快速创建并切换分支:git checkout -b [分支]:这条命令能够一次性完成创建新分支和切换到该分支的操作,简化了流程。
分支管理策略
-
Fast forward 模式
-
- 在通常情况下,当Git进行分支合并时,如果不存在冲突并且线性历史允许,它会采用 Fast forward(快进)模式。这种模式下,Git不会创建新的合并提交,而是简单地将当前分支的指针移动到被合并分支的最新提交位置。
-
- 使用Fast forward模式的优点是简洁的历史记录,但它有一个缺点:一旦删除了分支,从历史中就无法看出分支的存在和合并的过程。
-
普通合并模式
-
- 当存在冲突或使用 --no-ff 参数强制禁用 Fast forward 模式时,Git会在合并时生成一个新的提交,明确记录此次合并操作。
-
- 这种模式的好处是在分支历史上可以清晰地看出分支信息以及合并点,即使在分支被删除之后也能追溯到曾经的合并活动。
git merge --no-ff -m "描述信息" [分支名]
推荐做法:为了保持项目历史的清晰和可追踪性,合并我建议不要使用 Fast-forward ,而使用 no-ff 。这样做可以确保每次合并都被明确记录下来,有助于未来在工作时候的团队协作和后续的问题排查。
总结
事实上,这个Git确实不难