前端之 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
分支。
- 从