跳到主要内容

图解Git命令

Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理,是目前使用范围最广的版本管理工具

尽管Git是一个非常强大的工具,但我认为大多数人都会同意我的说法,即它也可以是。。。彻头彻尾的噩梦😐 一直觉得在脑海中想象使用Git时发生的事情非常有用:当我执行某个命令时,分支是如何交互的,它将如何影响历史?国外来自英属哥伦比亚的程序媛 Lydia Hallie《CS Visualized: Useful Git Commands》。在这篇文章里面,她通过生动形象的动画,以更加直观的方式,向开发者展示 Git 命令中的 merge、rebase、reset、revert、cherry-pick 等常用骚操作的具体原理

Merging

- Fast-forward (--ff)

当当前分支与正在合并的分支相比没有额外提交时,可能会发生快速向前合并,Git首先尝试执行最简单的选择 Fast-forward 模式合并不会创建新的提交,而是合并当前分支中合并的分支上的提交

在这里插入图片描述

现在,在dev分支上所做的所有更改都在master分支上可用。那么,No-fast-foward 是怎么回事?

- No-fast-foward (--no-ff)

如果您当前的分支与要合并的分支相比没有任何额外的提交,那就太好了,但不幸的是,这种情况很少发生!如果我们在当前分支上提交了要合并的分支没有的更改,git将执行No-fast-foward 合并。使用No-fast-foward合并,Git在活动分支上创建一个新的合并提交。提交的父提交指向活动分支和要合并的分支! 在这里插入图片描述 没什么大不了的,完美的合并!🎉master分支现在包含我们在dev分支上所做的所有更改。

Merge Conflicts

尽管 Git 擅长决定如何合并分支和向文件添加更改,但它不能总是自己做出这个决定🙂 当我们尝试合并的两个分支在同一个文件的同一行有更改时,可能会发生这种情况,或者如果一个分支删除了另一个分支修改的文件,等等。

在这种情况下,Git 会要求您帮助决定我们要保留两个选项中的哪一个!假设在两个分支上,我们编辑了README.md. 在这里插入图片描述 如果我们想合并dev到master,这将导致合并冲突:你希望标题是Hello!还是Hey!?

当试图合并分支时,Git 会告诉你冲突发生在哪里。我们可以手动删除不想保留的更改,保存更改,再次添加更改的文件,然后提交更改🥳

在这里插入图片描述 耶!尽管合并冲突通常很烦人,但它完全有道理:Git 不应该只假设我们想要保留哪些更改。

2.Rebasing

我们刚刚看到了如何通过执行git合并将更改从一个分支应用到另一个分支。将更改从一个分支添加到另一个分支的另一种方法是执行git rebase。 在这里插入图片描述 完美,我们现在在分支上进行的所有更改都master可以在分支上使用dev!🎊

与合并相比,一个很大的区别是 Git 不会尝试找出要保留和不保留的文件。我们正在变基的分支总是有我们想要保留的最新更改!通过这种方式,您不会遇到任何合并冲突,并保持良好的线性 Git 历史记录。

这个例子展示了基于master分支的变基。然而,在更大的项目中,您通常不想这样做。Agit rebase 更改项目的历史,因为为复制的提交创建了新的哈希!

每当您在功能分支上工作并且主分支已更新时,重新定基都很棒。您可以获得分支上的所有更新,这将防止未来的合并冲突!😄

Interactive Rebase

在重新提交提交之前,我们可以修改它们!😃 我们可以通过交互式 rebase做到这一点。交互式变基对于您当前正在处理的分支也很有用,并且想要修改一些提交。

我们可以对我们正在变基的提交执行 6 项操作:

  • reword:修改提交信息

  • edit:修改此提交

  • squash:将当前提交合并到之前的提交中

  • fixup:将当前提交合并到之前的提交中,不保留提交日志消息

  • exec:在每一个需要变基的提交上执行一条命令

  • drop:删除提交

惊人的!这样,我们可以完全控制我们的提交。如果我们想删除一个提交,我们可以drop这样做。 在这里插入图片描述 或者,如果我们想将多个提交压缩在一起以获得更清晰的历史记录,没问题! 在这里插入图片描述 交互式变基使您可以对尝试变基的提交进行大量控制,即使在当前活动分支上也是如此!

Resetting

我们可能会提交我们以后不想要的更改。也许它是一个WIP提交,或者可能是一个引入错误的提交!🐛 在这种情况下,我们可以执行git reset.

Agit reset摆脱了所有当前暂存的文件,让我们可以控制HEAD应该指向的位置。

Soft reset

软重置移动HEAD到指定的提交(或提交的索引与 相比HEAD),而不会消除之后在提交中引入的更改!

假设我们不想保留9e78i添加style.css文件的提交,也不想保留035cc添加index.js文件的提交。但是,我们确实希望保留新添加的style.css文件index.js!软重置的完美用例。

在这里插入图片描述

键入 时git status,您会看到我们仍然可以访问对先前提交所做的所有更改。这很棒,因为这意味着我们可以修复这些文件的内容并在以后再次提交它们!

Hard reset

有时,我们不想保留某些提交引入的更改。与软重置不同,我们不再需要访问它们。Git 应该简单地将其状态重置回指定提交时的状态:这甚至包括工作目录和暂存文件中的更改!💣

在这里插入图片描述

Git 丢弃了在9e78i和上引入的更改035cc,并将其状态重置为提交时的状态ec5be。

Reverting

撤消更改的另一种方法是执行git revert. 通过还原某个提交,我们创建了一个包含还原更改的新提交!

假设ec5be添加了一个index.js文件。后来,我们实际上意识到我们不再希望这次提交引入的这种变化!让我们恢复ec5be提交。

在这里插入图片描述

完美的!提交9e78i还原了ec5be提交引入的更改。执行 agit revert对于撤消某个提交非常有用,而无需修改分支的历史记录。

Cherry-picking

当某个分支包含在活动分支上引入了我们需要的更改的提交时,我们可以cherry-pick使用该命令!通过cherry-picking 提交,我们在活动分支上创建了一个新提交,其中包含由cherry-picked 提交引入的更改。

假设分支76d12上的提交dev添加了对index.js我们想要在master分支中的文件的更改。我们不希望我们只关心这一次提交!

在这里插入图片描述

很酷,master 分支现在包含了76d12引入的更改!

Fetching

如果我们有一个远程 Git 分支,例如 Github 上的一个分支,则可能会发生远程分支具有当前分支没有的提交!也许另一个分支被合并了,你的同事推送了一个快速修复,等等。

git fetch我们可以通过在远程分支上执行 a 来在本地获取这些更改!它不会以任何方式影响您的本地分支:fetch只需下载新数据。

在这里插入图片描述

我们现在可以看到自上次推送以来所做的所有更改!既然我们在本地拥有新数据,我们就可以决定要如何处理这些数据。

Pulling

虽然 agit fetch对于获取分支的远程信息非常有用,但我们也可以执行 a git pull。Agit pull实际上是两个命令合二为一: agit fetch和 a git merge。当我们从源中提取更改时,我们首先像使用 a 一样获取所有数据git fetch,之后最新的更改会自动合并到本地分支中。

在这里插入图片描述

太棒了,我们现在与远程分支完美同步,并拥有所有最新更改!🤩

Reflog

每个人都会犯错,这完全没关系!有时你可能会觉得你把你的 git repo 搞砸了,以至于你只想完全删除它。

git reflog是一个非常有用的命令,用于显示已采取的所有操作的日志!这包括合并、重置、恢复:基本上是对分支的任何更改。

在这里插入图片描述

如果您犯了错误,您可以HEAD根据reflog提供给我们的信息轻松地重做此操作!

假设我们实际上并不想合并 origin 分支。当我们执行git reflog命令时,我们看到合并前的 repo 的状态是 at HEAD@{1}。让我们执行一个git reset指向 HEAD 回到它所在的位置HEAD@{1}!

在这里插入图片描述

我们可以看到最新的动作已经推送到了reflog!

Git 有很多有用的瓷器和管道命令,我希望我能把它们都介绍一遍!😄 我知道还有许多其他命令或更改我现在没有时间介绍 - 让我知道您最喜欢/最有用的命令是什么,我可能会在另一篇文章中介绍它们!

和往常一样,请随时与我联系!😊