【前端学习笔记】Git 原理及面试题

Git

    • 1.Git概念
    • 2.基本使用
    • 3.如果提交了错误代码,如何撤销或回滚?
    • [4.如果 git push 之后发现有错误,如何回滚远程仓库的提交?](#4.如果 git push 之后发现有错误,如何回滚远程仓库的提交?)
    • [5.Git merge 和 rebase 有什么区别?什么时候使用 rebase?](#5.Git merge 和 rebase 有什么区别?什么时候使用 rebase?)
    • [6.Git 合并时遇到冲突怎么办?](#6.Git 合并时遇到冲突怎么办?)
    • [7.Git 的三种状态是什么?](#7.Git 的三种状态是什么?)
    • [8. Git rebase 和 Git merge 的区别?](#8. Git rebase 和 Git merge 的区别?)
    • [9.如何还原已经 `git push` 的提交](#9.如何还原已经 git push 的提交)
    • [10.git pull 和 git fetch 有什么区别](#10.git pull 和 git fetch 有什么区别)
    • [11.git reset 原理详解](#11.git reset 原理详解)
    • [12.git stash 详解](#12.git stash 详解)

1.Git概念

Git 是分布式版本控制系统(DVCS)。它可以跟踪文件的更改,并允许你恢复到任何特定版本的更改。

Git 主要由以下几个区域组成:

  • 工作区(Working Directory):本地目录中实际存放的文件,即你正在编辑的代码。
  • 暂存区(Staging Area / Index) :使用 git add 命令后,变更会进入暂存区,准备提交。
  • 本地仓库(Local Repository) :使用 git commit 提交代码后,变更会存入本地仓库。
  • 远程仓库(Remote Repository):远程服务器上存储的 Git 仓库,如 GitHub、GitLab、Bitbucket。

下图展示了 Git 的基本数据流:

plaintext 复制代码
工作区  ->  暂存区  ->  本地仓库  ->  远程仓库
编辑    ->  git add  ->  git commit  ->  git push
概念 解释
仓库(Repository) 存储项目的所有版本历史,可以是本地仓库或远程仓库(GitHub, GitLab, Gitee 等)。
分支(Branch) 并行开发的方式,主分支(main 或 master)通常代表稳定版本,开发人员可创建新分支进行开发。
提交(Commit) 代码变更的快照,每次提交都会生成一个唯一的 SHA-1 哈希值。
工作区(Working Directory) 本地文件夹,开发者在其中进行修改。
暂存区(Staging Area) git add 后的变更存储区域,提交前的准备状态。
本地仓库(Local Repository) 本机上的 Git 仓库,存储提交的所有历史记录。
远程仓库(Remote Repository) 远程服务器上的 Git 仓库(如 GitHub/GitLab),用于团队协作。

2.基本使用

  1. 初始化仓库
sh 复制代码
git init
  • 用于在本地目录创建一个新的 Git 仓库,生成 .git 目录存放 Git 的所有版本控制信息。
  1. 克隆远程仓库
sh 复制代码
git clone <仓库地址>
  1. 查看当前 Git 状态
sh 复制代码
git status
  • 作用:显示工作区的文件变更情况,如新增文件、修改文件、未提交的更改等。
  1. 添加文件到暂存区
sh 复制代码
git add <文件名>
  • 例如:

    sh 复制代码
    git add index.html
  • 添加所有修改的文件:

    sh 复制代码
    git add .
  1. 提交代码从暂存区到本地仓库
sh 复制代码
git commit -m "提交信息"
git commit --amend -m "修改后的提交信息"
  1. 查看提交记录
sh 复制代码
git log
  • 作用:查看提交历史,包含提交哈希值、作者、日期、提交信息。

  • 以简洁方式显示:

    sh 复制代码
    git log --oneline --graph --all
  1. 推送代码从本地仓库到远程仓库
sh 复制代码
git push origin <分支名>
  1. 拉取远程仓库代码
sh 复制代码
git pull origin <分支名>
  • git pull = git fetch + git merge,即拉取代码并合并。
  1. 分支管理

创建新分支

sh 复制代码
git branch <分支名>

切换到某个分支

sh 复制代码
git checkout/switch <分支名>

创建并切换到新分支

sh 复制代码
git checkout/switch -b <分支名>

合并分支

sh 复制代码
git merge <分支名>

删除本地分支

sh 复制代码
git branch -d <分支名>

删除远程分支

sh 复制代码
git push origin --delete <分支名>

3.如果提交了错误代码,如何撤销或回滚?

  1. 仅仅修改了文件,还未 add

    git checkout -- file.txt # 撤销未 add 之前的修改

  2. 已经 add,但还未 commit

    git reset HEAD file.txt # 取消暂存
    git checkout -- file.txt # 恢复到上次提交状态

  3. 已经 commit,但还未 push

    git reset --soft HEAD~1 # 撤销 commit,保留代码
    git reset --hard HEAD~1 # 彻底删除 commit 和修改

4.如果 git push 之后发现有错误,如何回滚远程仓库的提交?

  1. 使用 git revert(推荐,保留历史)

    git revert <commit-hash> # 生成一个新的 commit,撤销错误提交
    git push origin main # 推送到远程仓库]

  2. 使用 git reset + 强制推送(⚠️ 不推荐,历史丢失)

    git reset --hard HEAD~1 # 本地回退到上一个提交
    git push --force origin main # 强制覆盖远程仓库

5.Git merge 和 rebase 有什么区别?什么时候使用 rebase?

merge(合并):

  1. 创建一个新的合并提交
  2. 有合并点(merge commit)
  3. 推荐使用共享分支
  4. 可以保留分支历史

rebase(变基):

  1. 将新分支的提交 重新应用 到目标分支
  2. 提交历史更直线化
  3. 不推荐用于共享分支

6.Git 合并时遇到冲突怎么办?

  1. 拉取最新代码:git pull origin main

  2. 尝试合并:git merge feature-branch

  3. 使用 git status 查看冲突文件。

  4. 编辑冲突文件,手动修改

  5. 标记冲突解决:

    git add file.txt
    git commit -m "解决冲突"

  6. 推送代码:git push origin main

7.Git 的三种状态是什么?

  • 已修改(Modified):文件内容被修改,但未添加到暂存区。
  • 已暂存(Staged) :使用 git add 将修改放入暂存区,准备提交。使用git add实现, git reset HEAD <文件名>撤回
  • 已提交(Committed) :提交到本地仓库,版本被记录。使用git commit实现,使用git reset --soft HEAD^ 撤回。

8. Git rebase 和 Git merge 的区别?

  • git merge 会创建一个新的合并提交(merge commit),历史记录有分叉。
  • git rebase 会把当前分支的提交放到目标分支的最新提交之后,历史记录更直线化。

Git cherry-pick 是什么?

sh 复制代码
git cherry-pick <提交哈希>
  • 作用:从另一个分支中挑选特定提交合并到当前分支,而不是合并整个分支。

9.如何还原已经 git push 的提交

  1. git revert 用于撤销某个提交,但不会修改提交历史,而是创建一个新的提交来抵消之前的更改。git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

    sh 复制代码
    git log --oneline (找到要车型的commit ID
    git revert ID
    git push origin main (推送
  2. git reset --hard 会直接回滚到指定的 commit,并丢弃所有之后的提交,但是需要 git push --force,如果有别人在这个提交之后,那会丢失。

sh 复制代码
git log --oneline 
git reset --hard ID
git push origin main --force
  1. git reset --soft:仅撤销 commit ,但保留文件变更,也就是修改commit信息或合并commit。

    sh 复制代码
    git reset --soft HEAD~1 回退一个提交
    git commit -m "修改后的提交信息"
    git push origin main --force
    • 如果其他人已经拉取了你的提交,这样可能会导致他们的本地分支混乱,需要谨慎使用!
  2. git reflog + git reset(找回误删的提交)

    如果你误用了 git reset --hard 丢失了提交,可以用 git reflog 找回它。

    sh 复制代码
    git reflog 查看所有历史操作
    git reset --hard id 恢复误删的提交
    git push origin main --force
  3. git cherry-pick(恢复某个被删除的 commit)**

    如果你已经 reset --hard 丢失了某个提交,但 git reflog 还能找到它,你可以使用 git cherry-pick 恢复它。

    sh 复制代码
    git reflog
    git cherry-pick <commit-id>
    git push origin main
目标 推荐方式
撤销一个错误的提交,但保留历史 git revert <commit-id>
彻底删除某个提交,不保留历史(慎用) git reset --hard <commit-id> && git push --force
撤销最近的提交,但保留代码 git reset --soft HEAD~1
误删 commit 后恢复 git reflog + git reset --hard <commit-id>
恢复单个误删的 commit git cherry-pick <commit-id>

10.git pull 和 git fetch 有什么区别

git fetch:仅下载远程仓库的最新更新,不会自动合并到当前分支。只是下载远程的 commit 信息,不会影响你的工作区(Working Directory)或暂存区(Staging Area)。

git pull:相当于 git fetch + git merge,拉取并自动合并远程更新到当前分支。git pull 会执行 merge,可能会生成额外的 merge commit,使用git pull --rebase origin main可以避免。

11.git reset 原理详解

git reset 的作用是在不同的 Git 版本之间移动分支指针,并可以选择是否修改暂存区(Staging Area)和工作区(Working Directory)。

  • HEAD:指向当前分支的最新提交(commit)。
  • 分支指针(Branch Pointer):HEAD 实际上指向的是某个分支,而分支指针指向某个 commit。
  • 索引(Index 或 Staging Area) :暂存区,用于存放 git add 之后但未 commit 的变更。
  • 工作区(Working Directory):本地文件系统中的代码,即开发者正在编辑的文件。

Git 的 reset 主要影响 HEAD 指针、索引(暂存区)和工作区,其不同模式决定了这些区域的变化。

Git reset 主要有三种模式:

模式 作用 影响
git reset --soft 仅移动 HEAD,不影响暂存区和工作区 提交记录被撤销,但变更仍然在暂存区
git reset --mixed(默认) 移动 HEAD ,同时清空暂存区,但不修改工作区 代码仍在工作区,但需要重新 git add
git reset --hard 移动 HEAD,并强制修改暂存区和工作区 代码被还原,未提交的变更会丢失

Git 的 reset 主要做了三件事:

  1. 移动 HEAD 指针 到指定的 commit。
  2. 更新暂存区(Index),使其与新的 HEAD 匹配。
  3. 更新工作区(Working Directory) ,可选(仅 --hard 执行)。

  1. git reset --soft(仅移动 HEAD,不影响暂存区和工作区):仅回退提交,代码仍在暂存区。适用于想撤销 git commit 但不影响代码,准备重新提交。
sh 复制代码
git reset --soft HEAD~1

原理:

  • HEAD 移动到前一个 commit(HEAD~1)
  • 暂存区(index)保持不变
  • 工作区(Working Directory)保持不变
  1. git reset --mixed(HEAD 移动,并清空暂存区,但代码保留):回退提交,并清空暂存区,代码仍在工作区。想撤销 commit,并重新 git add 选择要提交的文件。
sh 复制代码
git reset --mixed HEAD~1

原理:

  • HEAD 移动到前一个 commit
  • 暂存区(Index)清空
  • 工作区(Working Directory)不变
  1. git reset --hard(彻底回退 HEAD,并还原工作区):回退提交,并清空暂存区和工作区(代码被删除)。完全恢复到上一个 commit,丢弃所有未提交的代码。
sh 复制代码
git reset --hard HEAD~1

原理:

  • HEAD 移动到前一个 commit
  • 暂存区(Index)同步为 HEAD
  • 工作区(Working Directory)同步为 HEAD

git resetgit checkout 的区别

对比项 git reset git checkout
作用 移动 HEAD,影响提交历史 切换分支或恢复文件
是否改变历史 ✅ 可能改变 ❌ 不改变
是否影响工作区 --soft--hard 可能影响

git reset vs git revert

操作 git reset git revert
影响历史 ✅ 可能删除提交 ❌ 保留历史
是否影响远程 ✅ 需要 push --force ❌ 不影响远程
适合多人协作 ❌ 不适合 ✅ 推荐

12.git stash 详解

git stash 是 Git 提供的一个临时存储 功能,它允许你保存当前的未提交更改,然后清空工作区,让你可以切换分支或执行其他操作,而不丢失当前的工作内容。

  • 作用:临时存储未提交的修改,并在需要时恢复。
  • 使用场景
    • 你正在修改代码,但需要切换到其他分支,而不想提交当前更改。
    • 你想暂时保存工作,然后拉取最新代码再继续开发。
    • 你正在修复 bug,需要临时存储当前开发进度。

  1. 保存当前更改**
sh 复制代码
git stash
  • git stash :存储暂存区和未暂存的修改
  • git stash -u:存储暂存区和未暂存和新增文件的修改。
  • git stash --keep-index 仅保存未暂存且不是新增的文件的修改。
  1. 恢复 stash 中的更改
sh 复制代码
git stash pop
  • 作用:从 stash 取出最近存储的更改,并应用到当前分支,同时删除该 stash 记录。

如果不想删除 stash 记录,而只是恢复修改:

sh 复制代码
git stash apply
  • 作用:恢复 stash 存储的更改,但不删除 stash 记录。

  1. 查看所有 stash 记录
sh 复制代码
git stash list
  • 作用:查看所有 stash 记录。

  1. 恢复指定 stash 记录
sh 复制代码
git stash apply stash@{1}
  • 作用:恢复 stash@{1} 里的内容,但不会删除该 stash 记录。

  1. 删除 stash 记录
sh 复制代码
git stash drop stash@{0}
  • 作用:删除 stash@{0} 记录,不影响其他 stash 记录。

删除所有 stash 记录:

sh 复制代码
git stash clear
  • 作用:彻底清空所有 stash。

git stash 使用场景

场景 使用命令
保存当前更改 git stash
恢复最新的 stash git stash pop
查看所有 stash 记录 git stash list
恢复指定的 stash git stash apply stash@{1}
删除指定 stash git stash drop stash@{0}
清除所有 stash git stash clear
保存未跟踪文件 git stash -u
仅 stash 暂存区的更改 git stash --keep-index
带描述的 stash git stash save "修复登录 Bug"

git stash vs. git reset vs. git checkout

操作 作用 是否影响提交历史 是否保留修改
git stash 临时存储未提交的修改 ❌ 不影响 ✅ 保留(可恢复)
git reset 撤销 commit 或暂存区修改 ✅ 影响(会回滚 commit) 🚫 不一定(--hard 会删除)
git checkout 切换分支,可能丢失未提交修改 ❌ 不影响 🚫 可能丢失
相关推荐
打野赵怀真22 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Riesenzahn23 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn24 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript
tommyrunner25 分钟前
Cursor rule文件测试 一秒了解AI行为规则文件
前端·cursor
北京_宏哥31 分钟前
《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
java·前端·selenium
Nu1135 分钟前
weakMap 和 weakSet 原理
前端·面试
顾林海37 分钟前
深入理解 Dart 函数:从基础到高阶应用
android·前端·flutter
比特鹰41 分钟前
桌面端跨端框架调研
前端·javascript·前端框架
Ratten42 分钟前
【JavaScript】---- JS原生的深拷贝API structuredClone 使用详解与注意事项
前端·javascript