写点什么

推荐收藏 | 【Git 实战专题】「必坑宝典」带你深入剖析 Git 操作指令下的奥秘原理和运作机制

作者:洛神灬殇
  • 2024-01-22
    江苏
  • 本文字数:3478 字

    阅读完需:约 11 分钟

推荐收藏 | 【Git实战专题】「必坑宝典」带你深入剖析Git操作指令下的奥秘原理和运作机制

前提介绍

Git 是一个分布式版本控制系统,它可以跟踪文件的修改、记录历史版本,并支持多人协作开发。



上面是 Git 中最常用的命令,用于在工作目录、暂存目录(也称为索引)和仓库、远程仓库之间复制文件。

常用的 Git 命令

跳步级别操作

直接跳过缓存区-提交代码

直接从仓库中取出文件或者直接提交代码,而无需经过暂存区域。这种方式可以简化 Git 的工作流程。以下是相关的命令。

git commit -a

git commit -a 命令实际上是先执行 git add 来跟踪并准备所有的更改(在当前工作目录中),然后执行提交(commit)。这会添加所有的修改到暂存区,并创建一个新的提交。



直接提交代码: git commit -a -m "<message>":使用-a选项可以跳过暂存区域,直接将所有已修改的文件提交到仓库。这样可以快速提交代码。


如果你在工作目录中有一些未追踪的更改,git commit -a 会自动将它们添加到暂存区,然后进行提交。如果你只想提交已经追踪的更改,那么使用 git commit 命令会更好,因为它不会自动添加未追踪的更改到暂存区。

直接跳过缓存区 - 回滚代码

git checkout -- files 这个命令的作用是将文件从暂存区复制到工作目录,覆盖掉工作目录中的修改,从而达到丢弃本地修改的目的。


在 Git 中,当你对文件进行修改后,这些修改默认是存放在工作目录下的。当你使用 git add 命令将文件添加到暂存区后,这些修改实际上已经被记录为“准备提交的更改”。



如果你想丢弃这些本地修改,你可以使用 git checkout -- files 命令。这里,files 是你想要恢复的文件的路径。执行这个命令后,这些文件会被恢复到你最后一次提交的状态,即丢弃了所有的本地修改。

git checkout HEAD -- files

git checkout HEAD -- files命令用于回滚到最后一次提交时的文件状态。它会将指定的文件恢复到最后一次提交时的状态,即复制最后一次提交的文件内容并覆盖当前工作目录中的对应文件。


  • git checkout:Git 命令,用于切换分支、恢复文件或检出文件。

  • HEAD:指向当前分支最新提交的指针。

  • --:用于分隔命令和文件路径。

  • files:要回滚的文件路径。


通过执行git checkout HEAD -- files命令,Git 会将指定的文件恢复到最后一次提交时的状态,即复制最后一次提交的文件内容并覆盖当前工作目录中的对应文件。这样可以撤销对文件的修改,回到最后一次提交的状态。

git 的 graphFlow 流程

在下面的图片中,我们可以看到一些颜色标识和字符表示的提交信息。这些信息有助于理解提交历史和分支结构。



  • 每一个提交节点都是 5 位字符进行表示,用于唯一标识每个提交。每个提交都有一个唯一的 ID,用于跟踪和引用。

  • 父节点是指向前一个提交的指针。通过父节点,我们可以追溯到提交的历史。

  • 历史分支用橘色点显示,并指向特定的提交。分支是指向某个提交的指针,它可以帮助我们在提交历史中标记和访问特定的位置。

  • 当前分支是有绿色点限时,附在其上的 HEAD 标识。HEAD 是一个特殊的指针,它指向当前所在的分支。通过 HEAD,我们可以知道当前所在的分支是哪个。


通过这些信息,我们可以更好地理解提交历史和分支结构。


git checkout <commit> -- <file>:从指定的提交中取出文件,并将其覆盖当前工作目录中的对应文件。这样可以恢复或查看历史版本的文件。

命令详解

Diff

有许多种方法可以查看两次提交之间的变动。


  1. 使用git diff <commit1> <commit2>命令来比较两次提交之间的差异。这将显示出两次提交之间文件内容的变化。

  2. 使用git diff <branch1> <branch2>命令来比较两个分支之间的差异。这将显示出两个分支之间文件内容的变化。

  3. 使用git log --oneline <commit1>..<commit2>命令来查看两次提交之间的提交历史。这将显示出这两次提交之间的所有提交记录。

Commit

Git 会使用暂存区域的文件创建一个新的提交,并将当前节点设为父节点。然后,Git 会将当前分支指向新的提交节点。在下图中,当前分支是 feature4.0。在运行命令之前,HEAD 指针指向 e43b1。提交后,HEAD 指针指向新的分支 feature5.0(a43b1),并将 e43b1 作为父节点。



通过这个过程,我们可以将新的更改保存为一个新的提交,并将分支指向该提交,使得分支的最新状态反映了这次提交。

前置分支提交

即使当前分支是某次提交的祖父节点,Git 仍然会执行相应的操作。在下图中,我们可以看到在 feature4.0 分支上进行了一次提交,生成了一个新的提交节点,标记为 a43b2。就形成了一个旁路 FlowGraph。



当分支之间存在这样的关系时,合并或者衍合操作是必要的。合并操作将两个分支的修改合并到一起,创建一个新的提交节点,以包含两个分支的修改。衍合操作则是将一个分支的修改应用到另一个分支上,创建一系列新的提交节点,以模拟另一个分支的修改历史。



通过合并或者衍合操作,我们可以将两个分支的修改整合在一起,保持分支之间的同步和一致性。

提交覆盖机制 amend

如果想更改一次提交,使用 git commit --amend。git 会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。

Checkout

git checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,同时也可以用于切换分支。


当给定某个文件名时(或者使用-p选项,或者同时给定文件名和-p选项),git checkout会从指定的提交中拷贝文件到暂存区域和工作目录。


例如,git checkout HEAD~ 文件名会将提交节点HEAD~(即当前提交节点的父节点)中的文件复制到工作目录,并将其添加到暂存区域中。



如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。这个操作不会改变当前分支。


当不指定文件名,而是给出一个(本地)分支时,git checkout命令会将HEAD标识移动到该分支,实现分支的切换。同时,暂存区域和工作目录中的内容会与HEAD对应的提交节点保持一致。


  • 当执行git checkout <branch>命令时,如果不指定文件名,而是给出一个(本地)分支名,Git 会将HEAD标识移动到该分支,实现分支的切换。这意味着我们现在处于指定的分支上,可以在该分支上进行操作。

  • 同时,暂存区域和工作目录中的内容会与HEAD对应的提交节点保持一致。这意味着新的提交节点中的所有文件都会被复制到暂存区域和工作目录中,以反映该提交的内容。

  • 与此同时,只存在于旧的提交节点中的文件会被删除,以保持与新的提交节点一致。而不属于上述两者的文件会被忽略,不受影响。

checkout 总结

git checkout命令可以用于从历史提交中获取文件的副本,并将其放入工作目录和暂存区域。这对于恢复特定版本的文件或者查看历史文件的内容非常有用。同时,git checkout也可以用于切换分支,但在这种情况下,需要使用不同的参数和选项。

Reset

git reset命令可以将当前分支指向另一个提交位置。如果不指定选项,那么当前分支将指向指定的提交。这样可以改变当前分支的位置,以便回退或者前进到不同的提交。

git reset命令选择性地修改工作目录和暂存区


  • --hard选项,工作目录和暂存区都会被更新,与指定的提交保持一致。这将丢弃工作目录和暂存区中的所有未提交的修改,慎用此选项。

  • --soft选项,工作目录和暂存区都不会被修改。当前分支仍然指向指定的提交,但工作目录和暂存区中的内容保持不变。这可以用于撤销最近的提交,而不影响工作目录和暂存区的内容。


如果没有给出提交点的版本号,那么默认用 HEAD。这样,分支指向不变,但是索引会回滚到最后一次提交,如果用--hard 选项,工作目录也同样。

Merge

git merge命令用于将不同的分支合并在一起。在执行合并之前,必须确保索引(暂存区)与当前提交保持一致。根据不同的情况,git merge命令会有不同的行为:


  1. 如果另一个分支是当前提交的祖父节点,那么合并命令将不做任何操作。这是因为当前提交已经包含了另一个分支的所有更改,所以不需要进行合并。

  2. 另一种情况是,如果当前提交是另一个分支的祖父节点,就会导致快速合并(fast-forward merge)。在这种情况下,合并操作只是简单地将分支指针向前移动,并生成一个新的提交。这是因为当前分支已经包含了要合并的分支的所有更改,所以不需要进行实际的合并操作。

Cherry Pick

git cherry-pick命令可以理解为在当前分支上“复制”一个提交节点,并在当前分支上创建一个完全相同的新提交。



具体来说,git cherry-pick命令的作用是选择一个或多个提交节点,并将这些提交节点的更改应用到当前分支上,创建一个新的提交。这个新的提交与原始提交节点的内容完全一样,但是在当前分支上进行了新的提交。


通过使用git cherry-pick命令,可以选择性地将其他分支或者提交中的更改应用到当前分支上,而不需要合并整个分支。这对于从其他分支中选择性地获取特定的更改非常有用。


注意,git cherry-pick命令会在当前分支上创建新的提交,而不会影响原始提交节点的状态。这意味着原始提交节点仍然存在于其原始分支上,并且在当前分支上只是创建了一个新的提交。

发布于: 刚刚阅读数: 4
用户头像

洛神灬殇

关注

🏆 InfoQ写作平台-签约作者 🏆 2020-03-25 加入

👑 后端技术架构师,前优酷资深工程师 📕 个人著作《深入浅出Java虚拟机—JVM原理与实战》 💻 10年开发经验,参与过多个大型互联网项目,定期分享技术干货和项目经验

评论

发布
暂无评论
推荐收藏 | 【Git实战专题】「必坑宝典」带你深入剖析Git操作指令下的奥秘原理和运作机制_Java_洛神灬殇_InfoQ写作社区