前端之 Git
1. Git 核心概念
理解 Git 的工作流程,首先要理解它的四个核心区域:
- 工作区 (Working Directory):你在电脑上能看到的目录,就是你的本地项目文件。
- 暂存区 (Staging Area / Index) :一个临时的存储区域,用于存放你想要在下一次提交中包含的更改。git add命令就是将工作区的修改添加到暂存区。
- 本地仓库 (Local Repository) :一个位于你本地计算机上的 .git目录,它包含了项目的所有版本历史。git commit命令将暂存区的内容永久保存到本地仓库。
- 远程仓库 (Remote Repository) :托管在网络服务器上的项目版本库(如 GitHub, GitLab),用于团队协作和数据备份。git push将本地仓库的提交推送到远程仓库。
数据流向图: 工作区 -> git add -> 暂存区 -> git commit -> 本地仓库 -> git push -> 远程仓库
2. 高频命令
这些是日常开发中使用频率最高的命令。
| 命令 | 功能描述 | 
|---|---|
| git init | 在当前目录初始化一个新的 Git 仓库。 | 
| git clone [url] | 从远程仓库克隆一个项目到本地。 | 
| git status | 查看工作区和暂存区的状态。 | 
| git add [file] | 将指定文件的修改添加到暂存区 ( .代表所有文件)。 | 
| git commit -m "[message]" | 将暂存区的内容提交到本地仓库,并附上提交信息。 | 
| git push [remote] [branch] | 将本地分支的提交推送到远程仓库。 | 
| git pull [remote] [branch] | 从远程仓库拉取最新内容并合并到当前分支(相当于 git fetch+git merge)。 | 
| git log | 查看提交历史记录。 | 
| git branch | 查看、创建或删除分支。 | 
| git checkout [branch] | 切换到指定分支。 | 
| git merge [branch] | 将指定分支的更改合并到当前分支。 | 
| git reset [commit] | 回退版本,可以撤销提交。 | 
| git revert [commit] | 创建一个新的提交来撤销指定的提交,更安全。 | 
3. 分支管理
分支是 Git 的核心功能之一,它允许并行开发而不互相干扰。
常见分支策略
- Git Flow : 一种相对复杂但非常规范的分支模型,定义了 master,develop,feature,release,hotfix等多种分支类型,适合大型、需要版本发布管理的项目。
- GitHub Flow : 一种更轻量级的分支模型。master分支始终是可部署的,任何新功能的开发都在一个单独的feature分支上进行,完成后通过 Pull Request (PR) 合并到master。适合持续部署的项目。
分支操作
- git branch:列出所有本地分支。
- git branch [branch-name]:创建一个新分支。
- git checkout -b [branch-name]:创建并立即切换到新分支。
- git branch -d [branch-name]:删除一个已经合并的分支。
- git branch -D [branch-name]:强制删除一个分支(无论是否已合并)。
4. 冲突解决
当多个分支修改了同一个文件的同一部分并尝试合并时,就会产生冲突。
解决步骤:
- 
执行 git merge或git pull后,Git 提示存在冲突。
- 
使用 git status查看冲突文件。
- 
打开冲突文件,你会看到类似以下的标记: scss<<<<<<< HEAD (当前分支的修改) // some code ======= // other code >>>>>>> [other-branch-name] (待合并分支的修改)
- 
手动编辑文件,删除这些特殊标记,并决定保留哪部分代码(或两者都保留,或进行修改)。 
- 
保存文件后,使用 git add [conflicted-file]将解决后的文件标记为已解决。
- 
最后执行 git commit完成合并。
5. 高级应用
git rebase (变基)
- 作用:将一个分支的提交历史"变基"到另一个分支上,使提交历史看起来更整洁,形成一条直线。
- 与 merge的区别 :- merge会保留原始的提交历史,并在合并时创建一个新的"合并提交"。历史记录是分叉的。
- rebase会重写提交历史,将当前分支的提交在目标分支上"重放"一遍。历史记录是线性的。
 
- 风险 :不要在已经推送到公共远程仓库的共享分支上使用 rebase,因为它会改变提交的 SHA-1 哈希值,可能给协作者带来麻烦。
git stash (贮藏)
- 场景 :当你正在开发一个功能,但突然需要切换到另一个分支修复一个紧急 bug 时,可以使用 git stash。
- 作用:将工作区和暂存区的未提交的修改临时保存起来,让你的工作目录变干净。
- 常用命令 :
- git stash或- git stash save "message":保存当前修改。
- git stash list:查看所有保存的贮藏。
- git stash pop:恢复最近一次的贮藏,并从贮藏列表中删除它。
- git stash apply:恢复最近一次的贮藏,但保留在列表中。
- git stash drop:删除一个贮藏。
 
git cherry-pick (拣选)
- 作用:将另一个分支上的某一个或几个特定的提交应用到当前分支。
- 场景:当其他分支的某个功能修复或提交对当前分支也有用,但你又不想合并整个分支时,可以使用它。
- 用法 :git cherry-pick [commit-hash]。
6. 面试真题
1. git pull 和 git fetch 有什么区别?
- git fetch:从远程仓库下载最新的对象(如提交、文件、分支引用),但不会 自动合并或修改你当前的工作。它只是更新你的本地仓库中远程分支的镜像(如- origin/master)。
- git pull:相当于- git fetch之后立即执行- git merge。它会从远程仓库拉取最新版本,并尝试将其合并到你当前的本地分支。
2. git reset 和 git revert 有什么区别?
- git reset:用于回溯历史,它会将 HEAD 指针移动到指定的提交,工作区和暂存区的内容会根据参数(- --soft,- --mixed,- --hard)不同而改变。这会改变历史记录 。- --soft: 只移动 HEAD,不改变暂存区和工作区。
- --mixed(默认): 移动 HEAD,重置暂存区,不改变工作区。
- --hard: 移动 HEAD,重置暂存区和工作区(危险,未提交的修改会丢失)。
 
- git revert:用于"撤销"一个提交,但它是通过创建一个新的提交来抵消指定提交所做的更改。它不会改变项目历史,是一种更安全的回退方式,尤其适合在公共分支上操作。
3. git rebase 和 git merge 的核心区别是什么?该如何选择?
- 
核心区别: - git merge:会保留原始的、分叉的提交历史,并通过创建一个新的"合并提交"来整合分支。它忠实地记录了历史上发生过的一切。
- git rebase:会"重写"历史,将当前分支的提交在目标分支上"重放"一遍,从而形成一条干净的、线性的提交历史。
 
- 
如何选择: - 使用 merge:当你希望保留完整的、真实的合并历史时;当你在一个共享的、多人协作的分支上工作时(如main,develop)。这是更安全、对团队更友好的选择。
- 使用 rebase:当你准备将自己的个人开发分支 合并到主分支之前,可以用它来整理自己的提交记录,让历史变得清晰。
- 黄金法则 :永远不要对一个已经推送到远程并被他人使用的公共分支进行 rebase操作,因为它会改变提交的 SHA-1 哈希值,可能给协作者带来麻烦。
 
- 使用 
4. 如何撤销最近一次的提交?
- 如果提交还未推送到远程仓库:
- git reset --soft HEAD~1:撤销提交,但保留更改在暂存区。可以重新提交。
- git reset --hard HEAD~1:彻底撤销提交和所有相关更改(慎用)。
 
- 如果提交已经推送到远程仓库:
- git revert HEAD:创建一个新的提交来撤销上一次提交,然后- git push。这是最安全的方式。
 
5. 你在工作中是如何使用 Git 的?可以描述一下你的工作流吗?
- 这是一个开放性问题,可以结合你公司的实际情况回答。可以描述使用 GitHub Flow 的流程:
- 从 main(或develop) 分支创建一个新的feature分支。
- 在 feature分支上进行开发和提交。
- 定期从 main分支拉取最新代码并合并到feature分支,解决冲突。
- 功能完成后,将 feature分支推送到远程仓库。
- 在 GitHub/GitLab 上创建一个 Pull Request (PR) 或 Merge Request (MR)。
- Code Review 后,将 PR/MR 合并到 main分支。
- 删除远程和本地的 feature分支。
 
- 从 
6. 如果需要临时修复一个线上的紧急 Bug,你会怎么做?
- 这通常会用到 hotfix分支:- 从 master(或main) 分支检出一个hotfix分支。
- 在 hotfix分支上进行修复并提交。
- 测试通过后,将 hotfix分支合并回master并打上新的标签发布。
- 同时,也需要将 hotfix分支合并到develop分支,以确保开发分支也包含了这个修复。
- 删除 hotfix分支。
 
- 从