本文概述
每个开发人员都应该对版本控制有充分的了解, 而Git已成为软件开发中事实上的版本控制标准。
但是, 开发人员通常只学习一些简单的命令, 而忽略了Git历史记录的功能以及Git可以做的其他事情, 这些使你更加高效。例如, 使用git标签使用Git管理发布非常容易。
我与Github一起在线学习了Git的高级课程, 然后与Github一起教了初学者的Git课程。当我发现关于我最喜欢的Git功能的技术文章并不多时, 我跳开了与其他开发人员共享它的机会。在本文中, 你将学习如何利用以下高级Git功能:
- git stash, 它可以在本地临时保存代码
- git reset, 它使你可以在提交之前整理代码
- git bisect, 一个允许你找出错误提交的函数
- git squash, 它允许你合并提交
- git rebase, 它允许将一个分支上的更改应用于另一个分支
Git Stash
Git stash使你无需提交即可保存代码。这有什么用?描绘以下场景:
你已经进行了3次整洁的提交, 但是你还有一些未提交的代码, 这些代码非常混乱。如果不先删除调试代码, 你将不想提交它。然后, 由于某种原因, 你突然需要参加另一项任务, 并且不得不切换分支机构。如果你在主分支上, 并且忘记为该功能创建一个新分支, 通常会发生这种情况。现在, 你的代码如下所示:
当你运行git stash时, 未提交的代码会消失而不会被提交。存放就像将临时本地提交保存到分支一样。无法将存储空间推送到远程存储库, 因此存储空间仅供你个人使用。
现在, 你的分支显示为你上次提交时的样子。现在, 你可以安全地更改分支, 而不会丢失代码或进行混乱的提交。当你切换回分支并运行git stash list时, 你会看到类似以下内容的存储清单:
你可以通过运行git stash apply轻松地重新应用隐藏的内容。你还可以通过运行git stash apply [受电子邮件保护] {1}(如果” st”表示最后一个存储区的第二个), 来应用特定的存储区(如果已存储多次)。这是存储多个提交并应用不同存储的示例:
当我们将文本的颜色更改为红色时, git stash apply [受电子邮件保护] {2}已应用了最早的隐藏代码。
如果你决定在恢复存储后不提交工作, 则可以运行git checkout。, 它将重置所有未提交的代码。
再举一个使用Git stash的示例:假设你有一些新文件, 其中一个有bug。将所有可疑的错误文件(暂存的代码都暂存)都暂存, 然后再暂存该文件并解决问题。如果存放的文件不是问题, 则可以还原存放的文件。
你还可以通过使用git stash分支将隐藏的提交继续到新功能分支或调试分支:
请注意, 当你应用存储时, 不会删除该存储。你可以使用git drop单独删除存储区, 也可以使用git stash clear删除所有存储区:
Git重置
如果你确实遇到了意外提交一些混乱代码的情况, 则可以进行”软”重置。这意味着代码看起来好像尚未提交。然后, 你可以在进行更简洁的提交之前在IDE中整理代码。为此, 你可以运行git reset –soft HEAD〜1。这将重置最近的提交。你可以通过在〜之后更改数字来重置多个提交。 git reset –soft HEAD〜2。
Git重置更加令人困惑, 尤其是在教新的Git用户时。对于真正的错误, 应该保留软重置, 而隐藏可以用于交换代码进出。
你还可以执行硬重置(git reset –hard HEAD〜1)。这种类型的重置实际上会擦除你的上一次提交。你应该非常注意执行硬重置, 尤其是在推送分支时, 因为无法恢复提交。
Git Bisect
我最喜欢的Git工具是git bisect。我只需要几次, 但是当我这样做时, 它是无价的!我主要在大型代码库上使用它, 即使在进行了一些剧烈的调试之后, 仍然没有人找到根本原因的问题。
git bisect本质上是在两个给定的提交之间执行二进制搜索, 然后为你提供特定提交的详细信息。首先, 你需要对Git进行一次良好的提交, 而你知道自己的功能正在正常工作, 而对Git进行一次错误的提交。请注意, 只要你一次提交一个好, 一次提交一个坏, 这些提交就可以相隔数年(尽管你返回的时间越远, 它变得越困难!)。
git bisect最有趣的是, 你通常在启动时并不真正知道是谁编写了bug提交。找出错误的根源的兴奋不止一次导致了一些同事挤在我的计算机旁!
首先, 请查看越野车分支并找到好的提交。你需要检查提交历史记录, 找到提交哈希, 然后检查该特定提交并测试分支。一旦找到可以工作的好地方和坏点, 就可以运行git bisect。
在这种情况下, 文字在我们制作的网站上为红色(尽管可以使用UI设计器), 但我们不知道如何或何时将其设为红色。这是一个非常简单的示例, 在现实生活中, 你可能遇到的问题要少得多, 例如表格未提交/无法运行。
运行git日志时, 我们可以看到要选择的提交列表。
如果我在最近的提交哈希上打开网页, 则该文本为红色, 因此我知道有问题。
现在, 我们开始二等分, 并告诉Git我们有一个错误的提交。
现在我们回到过去, 尝试查找文本不是红色的提交。在这里, 我尝试检查我的第一次提交…
…并刷新网页…
文本不再是红色, 所以这是一个不错的提交!提交越新, 即越接近错误的提交, 效果越好:
Git现在会告诉你在找到正确的提交之前必须搜索多少个提交。 Git会遍历的提交数量取决于好提交与坏提交之间的提交数量(时间越长, Git需要迭代的次数越多)。
现在, 你需要再次测试分支, 看看问题是否已经消失。有时, 如果你定期更新模块, 可能会有些麻烦, 因为你可能需要在前端存储库中重新安装节点模块。如果有数据库更新, 则可能还需要更新。
git bisect会在你的好与坏提交中间自动检出一个提交。在这里, 估计找到错误提交的步骤。
刷新页面, 然后查看问题是否消失。问题仍然存在, 因此我们告诉Git这仍然是一个错误的提交。这次无需引用提交哈希, 因为Git将使用你已检出的提交。我们需要重复此过程, 直到Git遍历了所有可能的步骤。
刷新页面, 我们的问题再次消失, 所以这是一个不错的提交:
在这个阶段, Git发现了第一个错误的提交:
现在我们可以使用git show来显示提交本身并确定问题所在:
完成后, 你可以运行git bisect reset将分支重置为正常工作状态。
提交之间的距离越近, Git越容易发现问题, 但是我已经花了10步之前仍然很容易找到错误的提交。它不能保证能正常工作, 但大多数时候对我来说都是问题所在。恭喜, 你现在是代码考古学家!
Git提交
之前, 我曾全职为一家全球组织从事开源项目, 然后我很快了解到压缩或合并你的提交非常重要。我认为这是一个很好的习惯, 即使你的雇主并不需要这样做。对于需要审查和编辑你以后构建的功能的其他开发人员来说, 这尤其体贴。
为什么要压缩你的提交?
存储库的参与者可以更轻松地阅读。想象一下, 如果你有这样的提交列表:
- 实施轮播滑块
- 向旋转木马添加样式
- 将按钮添加到轮播
- 使用轮播修复IE中的奇怪问题
- 调整轮播中的边距
将这些内容压缩成一个单独的提交, 即”将轮播添加到首页”, 将更加容易。
如果每次发出拉取请求时都必须将提交压缩为一个, 则它鼓励你保持提交消息的理解性和相关性。你有多少次看到名为” WIP”, “登录页面的错误修正”或”修正错字”的提交。重要的是要具有相关的提交名称, 例如”#444登录页面的错误-修复由于缺少$ scope功能导致的闪烁”。
你可能不想压缩提交的原因可能是因为你正在使用非常详细和冗长的功能, 并且希望自己保留每日历史记录, 以防日后遇到错误。这样你的功能就更容易调试。但是, 当你将功能检入master分支并且确信它没有错误时, 挤压仍然很有意义。
在这种情况下, 我进行了五次提交, 但是所有这些都与一个功能相关。我的提交消息也与优点分开密切相关-我的所有提交都是关于为该新功能设置页面样式的:
你也可以使用git merge –squash, 但是我认为使用rebase更加清晰, 因为当你选择你的提交时, 更容易看到提交描述。如果你运行git merge –squash, 则首先必须对提交进行硬重置(git reset –hard HEAD〜1), 并且很容易混淆需要执行多少次提交。我发现git rebase更加直观。
首先运行git rebase -i, 命令行上的默认文本编辑器将打开, 其中包含你的提交列表:
你可能只想压缩最后的几次提交, 在这种情况下, 你可以运行git rebase -i HEAD〜2并向你显示最后的三次提交:
请注意, 如果你仅在本地运行Git, 并且尚未将分支推送到远程存储库, 则需要在此命令中添加–root, 即git rebase -i –root。这样可以防止分支因需要上游分支而受到限制。
现在, 我们可以将所有提交压缩到第一个提交中, 如下所示。
保存文件时, Git将打开你的提交消息以进行编辑。
在进行基准调整的同时, 我们还可以编辑提交描述, 以便于阅读。
再次保存此文件, 你就完成了!当我们再次查看Git日志时, 我们可以看到只有一个干净的提交。
Git Rebase
开发人员通常不愿使用git rebase, 因为他们知道可以使用rebase从你的代码库中永久删除文件。
正如我们在上面看到的, git rebase可用于保留你的代码并整理和删除它-但是, 如果你确实确实想从历史记录中永久删除文件, 该怎么办?
我曾经目睹过一个场景, 我们的开发团队的一个成员不小心将一个很大的文件提交给了代码库。它是更大分支的一部分, 因此大文件在代码审查中未被发现, 并被错误地检入master分支。每当有人想重新克隆存储库时, 这便成为一个问题-下载时间很长!当然, 该文件是不必要的。如果文件是对master分支的最后一次提交, 这不会有问题-在这种情况下, 你可以运行硬重置(git reset –hard〜1)并强制推送分支。
同样, 如果文件是给定提交中的唯一更改, 则可以通过运行git reset –hard commit-id删除整个提交。但是, 在我们的方案中, 大文件与我们想要保留在历史中的其他代码一起提交, 这是倒数第二次提交。
找到麻烦的提交后, 请使用git checkout和提交哈希将其检出。
删除文件, 或编辑你的代码, 并保留要保留的代码(或文件)。
确保运行git add -A, 以便暂存已删除的文件, 并且Git知道要删除它。现在运行git commit –amend -v, Git将要求你编辑提交消息。
之后, 使用自己的提交哈希值对HEAD 69aa621184e458f61bf09327c4e104b3e9bc8b6b master运行git rebase –on。在这里你可能会遇到一些合并冲突, 这意味着新提交和旧代码之间存在冲突。 Git会要求你解决冲突:
如果你在文本编辑器中打开文件, 则会看到Git标记了两个版本的索引文件。你只需要删除一个或编辑一个即可保留你喜欢的更改。
“«<HEAD”和等号行” ===”之间的代码是一个版本, ” ====”和”»> Add index file”之间的代码是” Add index file”提交的版本。因此, 你可以看到一个版本的另一段内容是” srcmini连接了全世界自由职业者中排名前3%的人才”, 而另一个版本则没有。
保存编辑后的文件并运行git add filename, 然后运行git rebase –continue。如果没有更改, 你也可以运行git rebase –skip。如果你的”大文件”提交与主服务器上的最新提交之间有很多提交, 则可能需要花一些时间来进行重新基准化。
请耐心等待, 如果你在大型团队中, 请确保获得其他意见!如果可能的话, 与编写你要合并的提交的人进行协商尤其重要。
请记住, 合并更改与历史记录中的特定提交相关, 而与你最新的更改无关。即如果你是从网站上的文本为Arial(现在是Verdana)开始编辑提交的, 则仍应保留该提交, 并以Arial的历史作为字体。
另请注意, 如果Git看到空格或行尾字符, 则可能导致合并冲突, 因此请小心!
不仅仅是提交和pull
Git比许多开发人员想象的要强大。如果你恰好要介绍新手, 请确保给他们一些有关这些宝贵功能的提示。它使工作流程更加高效。
想更多地了解Git?查看srcmini的Git技巧和实践页面。
评论前必须登录!
注册