我希望多年前就知道的 Git 概念目录 Git 命令其他 Git 技巧 Git 工作流

2025-05-24

我希望多年前就知道的 Git 概念

目录

Git 命令

其他 Git 技巧

Git 工作流

开发人员使用最多的技术不是 Javascript。

它不是 Python 或 HTML。

它甚至很少在面试中被提及或被列为工作先决条件。

我当然是在谈论 Git 和版本控制。

我们大多数人花了太长时间学习一些git 概念。我们在一个拥有简单功能分支工作流程的小团队中工作,只学到了最低限度的知识。如果你和我一样,这些知识将在你的职业生涯中持续多年。

替代文本

是时候重新审视 Git 了,它对于职业发展至关重要。本指南旨在提供一些我认为必不可少但鲜为人知的概念的参考。掌握 Git 将极大地改善您的代码管理方式和日常工作流程。由于 Git 命令略显陈旧且难以记忆,本指南将按概念和预期行为进行分类。

如果您对 Git 的常规概念(例如工作目录、本地仓库和远程仓库之间的区别)尚不熟悉,请先阅读本指南。同样,如果您尚未掌握基本的 git 命令,请先阅读官方文档。本指南并非旨在帮助您从零基础入门到精通,并且假设您已经具备一定的 Git 使用经验git

目录

Git 命令

📋 日志记录

我刚才做了什么?



git log
git log --oneline # more succinct output
git log --graph # with a visual graph of branches


Enter fullscreen mode Exit fullscreen mode

查看您的“撤消”历史记录



git reflog


Enter fullscreen mode Exit fullscreen mode

因为有时git log不起作用,特别是对于那些没有出现在提交历史中的命令。

reflog在运行诸如 之类的“可怕”命令后,它基本上就是你的安全网git rebase。你不仅可以看到你所做的提交,还可以看到导致你提交的每个操作。请参阅这篇 Atlassian 文章,了解更多关于 refs 工作原理的信息。

查看当前状态 + 任何合并冲突



git status


Enter fullscreen mode Exit fullscreen mode

虽然git status这是一个我们很早就学过的基本命令,但它作为内化 git 基础知识的学习工具的重要性值得反复强调。它还能帮助你完成复杂的 rebase 或 merge 操作。

查看暂存(或未暂存)更改中的差异



git diff --staged # for staged changes
git diff # for unstaged changes


Enter fullscreen mode Exit fullscreen mode

查看两个分支之间的差异



git diff branch1..branch2


Enter fullscreen mode Exit fullscreen mode

🧭 导航

我想看看我之前做了什么



git reset <commit-sha>


Enter fullscreen mode Exit fullscreen mode

这将取消提交和取消暂存这些更改,但将这些文件保留在工作目录中。

我想切换到另一个分支



git switch branch-name   # new syntax (as of Git 2.23)
git checkout branch-name # old syntax


Enter fullscreen mode Exit fullscreen mode

git checkout它可能有点令人困惑,因为它可以在文件分支级别工作。从Git 2.23开始,我们现在有了git restore(checkout file) 和git switch(checkout branch) 这两个选项,如果你刚开始使用 Git,我建议你使用这两个选项以避免checkout混淆。

我想回到我之前所在的分支



git switch -


Enter fullscreen mode Exit fullscreen mode

📝 修改

我把自己挖进了一个兔子洞,让我们重新开始吧



git reset --hard HEAD


Enter fullscreen mode Exit fullscreen mode

这将重置您的本地目录以匹配最新的提交并丢弃未暂存的更改

我想将文件重置回原来的状态



git restore <filename>     # new syntax (as of Git 2.23)
git checkout -- <filename> # old syntax


Enter fullscreen mode Exit fullscreen mode

我想撤消最后一次提交并重写历史记录



git reset --hard HEAD~1


Enter fullscreen mode Exit fullscreen mode

我想回溯 n 次提交



git reset --hard HEAD~n        # n is the last n commits
git reset --hard <commit-sha>  # or to a specific commit


Enter fullscreen mode Exit fullscreen mode

软重置、混合重置和硬重置之间有一个重要的区别。基本上:

  1. --soft:取消提交更改但保留这些更改
  2. --mixed(默认):取消提交和取消暂存更改,但更改仍保留在工作目录中
  3. --hard:取消提交、取消暂存和删除更改

我已经重写了历史记录,现在想将这些更改推送到远程存储库



git push -f


Enter fullscreen mode Exit fullscreen mode

当您的本地和远程存储库出现分歧时,这都是必要的。

警告:强制推送应格外谨慎。一般来说,在共享分支上应避免任何强制推送。在发起拉取请求之前,请将强制推送限制在您自己的分支上,以免无意中弄乱队友的 git 历史记录。

我想在上次提交中添加一些更改



git commit --amend


Enter fullscreen mode Exit fullscreen mode

我想在本地重写一堆提交



git rebase -i <commit hash> # where the commit hash is the one *before* all the changes you want to make


Enter fullscreen mode Exit fullscreen mode

这将打开一个交互式提示框,您可以在其中选择要保留、压缩或删除的提交。您还可以在此处更改提交消息。例如,在清理拼写错误或检查提交代码时,此功能非常有用。

我发现在深入学习 Git 时,rebasing 是最令人困惑的主题之一。更多信息请参阅rebasing部分。

这个 rebase 太乱了,我们放弃它吧



git rebase --abort


Enter fullscreen mode Exit fullscreen mode

你可以在 rebase 过程中执行此操作。我经常发现 rebase 带来的麻烦远大于其价值,尤其是在 rebase 两个包含大量相似更​​改的分支时。在 rebase 完成之前,你可以随时中止它。

我想从不同的分支引入提交



# From the branch you want to bring the commit *into*
git cherry-pick <commit-sha>


Enter fullscreen mode Exit fullscreen mode

我想从不同的分支引入一个特定的文件



git checkout <branch-name> <file-name>


Enter fullscreen mode Exit fullscreen mode

我想停止在版本控制中跟踪文件



git rm --cached <file-name>


Enter fullscreen mode Exit fullscreen mode

我需要切换分支,但目前的状态已损坏



git stash # saves your changes to the top of the stash stack
git stash save "message to go along with changes"
git stash -u # stash untracked files as well


Enter fullscreen mode Exit fullscreen mode

我想看看我的藏品里有什么



git stash list


Enter fullscreen mode Exit fullscreen mode

我想带回一些藏品



git stash pop # "pops" the most recent item added to the stash stack
git stash apply stash@{stash_index} # apply a given item in the stash (from git stash list)


Enter fullscreen mode Exit fullscreen mode

我想撤消提交而不重写历史记录



git revert HEAD # undo the last commit
git revert <commit hash> # for a specific commit


Enter fullscreen mode Exit fullscreen mode

这会将指定的提交的逆向操作重放为新的提交,从而撤消更改而不撤消历史记录。这是一种在共享分支上撤消提交的更安全的方法,因为重写历史记录的后果会更严重。

我想找到导致 bug 的提交



git bisect start
git bisect bad           # Current version is bad
git bisect good v1.1     # v1.1 is known to be good

git help bisect          # For more


Enter fullscreen mode Exit fullscreen mode

这个有点棘手,所以请参阅文档以了解更多信息。

🧹 清理

天啊我怎么会有这么多分支?



git branch --no-color --merged | command grep -vE "^(\+|\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d


Enter fullscreen mode Exit fullscreen mode

这将删除您本地除 master、developer 或 dev 之外的所有合并分支。如果您的主分支和 dev 分支名称不同,您可以grep相应地更改正则表达式。

这是一个需要记住的很长的命令,但是你可以将其设置为别名,如下所示:



alias gbda='git branch --no-color --merged | command grep -vE "^(\+|\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d'


Enter fullscreen mode Exit fullscreen mode

如果你使用 Oh My Zosh,以上步骤已经为你完成。更多信息请参阅别名部分

让我们对旧分支/分离提交进行垃圾回收



git fetch --all --prune


Enter fullscreen mode Exit fullscreen mode

如果您已设置远程存储库以在合并时删除分支,这也是一个非常有用的命令。

⌨️ 别名

Git 命令可能很长,而且很难记住。我们不想每次都输入它们,也不想花几天时间去记住它们,所以我强烈建议你为它们创建 git 别名。

更好的是,安装一个像Oh My Zosh这样的 Z shell (Zsh) 工具,你就能默认获得一堆最常用的 git 命令作为别名,并支持 Tab 补全。我懒得完全按照自己的意愿配置我的 shell,所以我喜欢像 Oh My Zosh 这样的开源工具,它们能帮我完成这些工作。更何况它自带的 shell 界面看起来也很漂亮。

我最喜欢使用的一些工具几乎每天都会用到:



gst - git status
gc  - git commit
gaa - git add --all
gco - git checkout
gp  - git push
gl  - git pull
gcb - git checkout -b
gm  - git merge
grb - git rebase
gpsup - git push --set-upstream origin $(current_branch)
gbda  - git branch --no-color --merged | command grep -vE "^(\+|\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d
gfa - git fetch --all --prune


Enter fullscreen mode Exit fullscreen mode

如果您忘记了这些别名或您自己设置的任何其他别名代表什么,您可以简单地运行:



alias


Enter fullscreen mode Exit fullscreen mode

或者搜索给定的别名:



alias grep <alias-name>


Enter fullscreen mode Exit fullscreen mode

其他 Git 技巧

忽略文件

许多文件不属于版本控制。您应该利用全局 gitignorenode_modules来实现这一点。例如,目录、.vscode其他 IDE 文件以及 Python 虚拟环境等不属于版本控制的内容。

对于任何敏感信息,您可以使用环境文件并将其添加到.gitignore项目根目录的本地。

特殊文件

你可能需要将某些文件标记为二进制文件,以便 Git 知道忽略它们,避免生成冗长的 diff 文件。Git 有一个.gitattributes专门用于此目的的文件。在 JavaScript 项目中,你可能需要添加yarn-lock.jsonpackage-lock.json,这样 Git 就不会在你每次进行更改时都尝试比较它们。



# .gitattributes
package-lock.json binary


Enter fullscreen mode Exit fullscreen mode

Git 工作流

变基 vs 合并

您的团队可以选择采用 rebase 或 merge 工作流程。两者各有利弊,而且我见过一些使用效果良好的案例。大多数情况下,除非您真的知道自己在做什么,否则最好选择 merge 工作流程。

即使您主要使用合并将更改引入生产环境,仍然可以有效地使用变基。最常见的情况是,您正在开发某个功能,而另一位开发人员将某个功能拉入了 master 分支。您当然可以使用变基git merge来引入这些更改,但现在您有了一个额外的提交,用于提交您队友所做的简单更改。您真正想要的是在新的 master 分支上重放您的提交。



git rebase master


Enter fullscreen mode Exit fullscreen mode

这应该会给你一个更清晰的提交历史。

要深入解释这种差异需要一整篇文章(博客文章待定),所以我建议您查看Atlassian关于这种差异的文档。

远程存储库设置

我最熟悉的是 Github 和 Gitlab,但是大多数其他远程存储库管理器应该都支持这些设置。

1. 合并时删除分支

合并完成后,您无需再关心分支,因为历史记录会反映在您的 master/dev 分支上。这显著减少了您需要管理的分支数量,也git fetch --all --prune更有效地保持本地仓库的整洁。

2. 防止直接推送到 master

如果没有这个,你可能会不小心忘记自己是在 master 分支上,然后执行 ,这很正常git push,很可能会破坏你的生产构建。这可不是什么好事。

3. 合并前至少需要一次批准

根据团队规模,合并前可能需要不止一次审批。即使你的团队只有两个人,最低也应​​该只有一个审批。你不必花费数小时来挑剔每一行代码,但通常情况下,你的代码应该有两双眼睛来审阅。反馈是学习和个人成长的关键。

4. 要求通过 CI 测试才能合并

无效的变更不应合并到生产环境中。审核人员无法 100% 地发现无效的变更,因此建议将这些检查自动化。无需赘述。

拉取请求

保持拉取请求简短精炼,理想情况下不超过几百行。小而频繁的拉取请求可以加快审核流程,生成更多无 bug 的代码,并减轻团队成员的工作负担。这还能提高工作效率,促进更多共享学习。与你的团队承诺,每天花一定时间审核未完成的拉取请求。

我们都喜欢回顾这些:
替代文本

如果您正在开发的功能会在一段时间内处于不稳定状态,请使用功能开关在生产环境中禁用它。这将防止您的功能分支与 dev/master 分支出现太大差异,并允许您更频繁地进行小型拉取请求。您越久不合并代码,以后合并就越困难。

最后,在你的拉取请求中添加详细的描述,必要时可以添加图片和/或动图。如果你使用 Jira 之类的工具来管理工单,请添加拉取请求对应的工单号。你的拉取请求描述得越详细、越直观,你的队友就越有可能愿意审阅它,而不是拖延。

分支命名

您的团队可能需要制定分支命名规范,以便于导航。我喜欢以您名字的首字母 + 姓氏开头,后跟一个正斜杠,并以连字符分隔分支描述。

这看起来可能微不足道,但使用制表符补全和 grep 等工具,这确实可以方便地查找和理解您可能拥有的所有分支。

例如,当我创建一个新分支时:



git checkout -b gabud/implement-important-feature


Enter fullscreen mode Exit fullscreen mode

一周后,当我忘记我的分支名称时,我可以开始输入git checkout gabud,按 TAB,然后我的 Z shell 会显示我所有可供选择的本地分支,而不会看到任何队友的分支。

提交消息

语言很重要。一般来说,我认为最好不要提交状态不正确的内容,并且每次提交都应该有一条简洁的消息,解释变更应该做什么。根据Git 官方建议,我认为提交消息最​​好使用现在时、命令式的语气。可以将每条提交消息想象成对计算机/git的一条命令,你可以将其添加到以下句子的末尾:

如果应用此提交,它将……

那么,以现在的命令式意义来说,一个好的提交信息的例子是:



git commit -m "Add name field to checkout form"


Enter fullscreen mode Exit fullscreen mode

现在显示的内容是:“如果应用了此提交,它将在结帐表单中添加姓名字段”。简洁明了。

最后的想法

这绝不是 Git 的全部学习内容。我建议您查看官方文档git help了解更多信息。不要害怕向队友寻求 Git 方面的帮助,你会惊讶地发现,大多数队友都有很多相同的问题。

那你呢?哪些 Git 命令或概念在你的工作流程中发挥了最大的作用?

文章来源:https://dev.to/g_abud/advanced-git-reference-1o9j
PREV
为什么我停止使用 Redux 单页应用程序的问题 Redux 不是缓存 更简单的后端状态方法
NEXT
为什么你不应该使用 Web 框架