Git基础知识

文章目录

1.Git概述

1.1什么是Git

Git 是由 Linus Torvalds 于 2005 年开发的分布式版本控制系统,用于高效追踪文件变更、管理代码历史、支持多人协作开发,是目前全球最主流的版本控制工具。

1.2Git的核心设计:快照式存储

Git 不存储文件的差异变更,而是在每次提交时生成整个项目的完整快照。对于未修改的文件,仅保留指向原文件的引用,既保证了速度,又确保了数据完整性。

1.3三大核心工作区域

Git 的所有操作都围绕这三个区域流转:

  1. 工作区(Working Directory):电脑上能直接编辑的文件目录。
  2. 暂存区(Staging Area):提交前的临时缓冲区,用于整理本次要提交的内容。
  3. 版本库(Repository):本地仓库,保存所有提交的历史快照和元数据。

1.4基本工作流程

Git 最基础的协作流程:

  1. 在工作区修改文件。

  2. git add:将修改添加到暂存区。

  3. git commit:将暂存区内容提交到本地版本库。

  4. git push:将本地提交推送到远程仓库。

2.Git VS SVN

Git(分布式)与 SVN(集中式)的核心区别源于架构设计的本质差异,并由此延伸出安全性、效率、工作流等多维度的不同。以下是清晰对比:

2.1核心架构差异

维度 SVN(集中式) Git(分布式)
仓库结构 仅有一个中央服务器保存完整版本库 每个开发者本地都有完整的版本库(含全部历史)
依赖关系 所有操作依赖中央服务器,服务器挂了全停工 本地可独立操作,仅同步时需与远程交互
类比 像 "图书馆",只有一本正本,大家只能借了改 像 "每人手里都有一本完整的书",自己改自己的,最后合并

2.2关键功能对比

  1. 安全性与数据备份

    SVN:风险高度集中 。中央服务器磁盘损坏或数据丢失,所有历史版本可能彻底丢失(仅靠本地最新代码无法恢复历史)。

    Git:极度安全。每个本地仓库都是完整备份,即使远程服务器挂了,随便找一个开发者的本地仓库就能恢复全部历史。

  2. 网络依赖(效率差异核心)

    SVN:几乎所有操作都需联网(查看历史、提交代码、对比版本等),网络差时效率极低。

    Git:90% 操作在本地完成(提交、查看历史、分支切换、代码对比等),无需联网,速度极快,仅在 "推送到远程" 或 "拉取他人代码" 时才需网络。

  3. 分支管理(体验差异最大)

    SVN:分支是 "目录复制",创建分支慢、切换慢,合并分支时易冲突且难处理,开发者通常不敢轻易建分支。

    Git:分支是 "指针移动",创建 / 切换分支仅需 0.01 秒,极其轻量,鼓励 "频繁分支、频繁合并"(如 Git Flow 工作流)。

  4. 工作流程灵活性

    SVN:线性工作流,必须先 "更新(update)" 再 "提交(commit)",否则容易冲突,且冲突解决麻烦。

    Git:非线性工作流,可本地多次提交、随意切换分支,支持 "先本地提交,后合并整理",适合复杂协作(如开源项目)。

3.Git本地常用命令

3.1设置、查看用户签名(config)

Git首次安装必须设置一下用户签名,用于区分不同操作者的身份,用户的签名信息在每次提交中都会展示。

  1. 设置用户签名。

    复制代码
    git config --global user.name 用户名
    git config --golbal user.email 邮箱
  2. 查看用户签名。

    复制代码
    git config --global user.name 
    git config --golbal user.email 

3.2初始化本地库(init)

  • 进入指定的目录后:

    复制代码
    git init 

3.3查看本地库状态(status)

复制代码
  git status

3.4添加和删除文件至暂存区(add、rm)

  • 添加hello.txt至暂存区。

    复制代码
    git add hello.txt
  • 删除暂存区中的hello.txt。

    复制代码
    git rm --cached hello.txt

3.5从暂存区提交文件至本地库(commit)

  • 从暂存区提交hello.txt至本地库。

    复制代码
    git commit -m "日志信息" hello.txt

3.6查看版本历史

命令 核心定位 核心特点
git log 查看可达的提交历史 展示提交节点、可同步到远程
git reflog 查看本地操作引用日志 记录所有本地操作、仅本地有效

3.6.1Git log(提交内容历史)

命令 功能描述
git log 查看当前分支完整提交历史(分页模式)
git log --oneline 简洁展示(一行一个提交,仅显示哈希前缀 + 提交信息)
git log -n 仅显示最近 n 条提交(例:git log -5
git log --graph 以图形化展示分支合并历史
git log --all 查看所有分支的提交历史

执行 git log 后终端进入 less 分页阅读器,退出方式:

  • 核心:按 q 键(quit)直接退出(无需回车);
  • 应急:按 Ctrl + C 强制退出;

3.6.2Git reflog(本地操作历史)

命令 功能描述
git reflog 查看 HEAD 的所有本地操作记录(最常用)
git reflog show 分支名 查看指定分支的操作记录(例:git reflog show dev
git reflog expire --expire=now --all 手动清理所有 reflog 记录(谨慎使用)

reflog 仅保存在本地,不会通过 git push 同步到远程;

默认保留 90 天未引用的记录,误操作后尽快恢复;

仅记录本地操作,其他开发者看不到你的 reflog

3.6.3核心区别总结

维度 git log git reflog
查看范围 仅可达的提交(未被删除 / 覆盖) 所有本地操作(含被删除的提交)
数据同步 可通过 push/pull 同步到远程 仅本地有效,不同步
核心用途 查看项目提交脉络、作者信息 恢复误操作(reset/rebase/ 删分支)
数据保留 永久(除非手动删除提交) 默认 90 天自动清理

3.7版本穿梭(checkout VS reset)

  1. git checkout <版本号>临时查看历史版本,不修改当前分支,进入 "分离头指针" 状态。

  2. git reset --hard <版本号>强制回退当前分支到指定版本,并丢弃所有后续提交和未保存的修改。

    1. 回退到上一个版本:git reset --hard HEAD^
    2. 回退到上上一个版本:git reset --hard HEAD^ ^
  3. 参考示例:当前master分支的版本历史:A → B → C → D(master 指向 D)

    1. 使用git checkout B,临时查看B版本的代码,同时将HEAD 指针 指向该版本(detached HEAD),但不移动当前分支的指针(master 仍然指向 D)

      复制代码
      A → B → C → D  master
           ^
           HEAD

      注意事项:

      1. 在分离头指针状态下可以正常查看代码、编译、测试,但是在此状态下提交代码,这些提交不会属于任何分支,当你切换回其他分支时,这些提交会被 Git 视为 "垃圾"删除。
      2. 如果想要在当前分支的某个版本上开发代码,可以使用git checkout -b temp <版本号>,来创建一个基于指定版本号的新分支,顺利解决分离头指针状态下无法提交代码的问题
    2. 使用git reset --hard B,将当前分支指针 移动到指定版本,同时强制重置工作区和暂存区的内容到该版本。

      复制代码
      A → B  master
           ^
           HEAD
      1. 工作区和暂存区的所有未提交修改会被永久删除
      2. 当前分支指定版本之后的提交会被删除(短时间内可以通过Git命令恢复)。
      3. 误操作后的恢复方法 :如果不小心执行了错误的git reset --hard,可以通过git reflog命令找到之前的提交哈希,然后再次执行git reset --hard <哈希值>恢复。

4.Git分支操作(branch)

4.1查看分支

  1. 查看分支名 + 最新提交哈希 + 最新提交信息。

    复制代码
    git branch -v
  2. 查看本地分支+关联的远程分支。

    复制代码
    git branch -vv
  3. 建立本地分支(master)与远程分支(origin/master)的关联关系

    复制代码
    git checkout master
    git branch -u origin/master 
  4. 查看所有分支(本地+远程)。

    复制代码
    git branch -a
  5. 查看远程分支。

    复制代码
    git branch -r
  6. 重命名本地分支。

    复制代码
    git branch -m oldName newName

4.2创建分支(branch)

  1. 基于当前分支的最新提交创建一个新的分支(temp)。

    复制代码
    git branch temp
  2. 创建并切换到新的分支,适用于临时开发、修复和实验性任务。

    • 基于当前分支的最新提交,创建并切换到新的分支(temp)。

      复制代码
      git checkout -b temp
    • 基于指定分支(dev)的最新提交,创建并切换到新的分支(temp)。

      复制代码
      git checkout -b temp dev
    • 基于指定版本(a1b2c3d4),创建并切换到新的分支(temp)。

      复制代码
      git checkout -b temp a1b2c3d4

4.3切换分支(checkout)

  1. 切换分支。

    复制代码
    git checkout 分支名
    1. 未 add、未 commit 的修改属于工作区 / 暂存区内容,不属于任何分支。如果在这时切换分支,那么修改的内容不会被丢弃,也不会自动提交,而是会被带到目标分支。
    2. 切换分支前,必须保持工作区是干净的(commit或者stash),防止代码污染。

4.3.1Git Stash(临时暂存)

4.3.1.1概念介绍
  1. 基本介绍:用于临时寄存当前分支未提交的所有修改(工作区、暂存区改动),快速清空本地工作区,达到干净状态。
  2. 适用场景:代码编写到一半,需要临时切换分支、紧急改 Bug、拉取最新代码,又不想生成临时 WIP 提交。
  3. 核心作用:本地草稿箱,临时存代码,安全切换分支,符合大厂协作规范。
4.3.1.2常用命令
  1. 暂存:

    • 基础暂存:默认寄存所有已修改、已暂存的内容。

      复制代码
      git stash
    • 带备注暂存(工作推荐):便于区分多条暂存记录,防止遗忘。

      复制代码
      git stash push -m "备注信息"
    • 包含新文件一起暂存:默认不保存未追踪的新文件,加 -u 可一并寄存。

      复制代码
      git stash -u
  2. 查看所有暂存记录。

    复制代码
    git stash list
  3. 恢复暂存。

    • 默认恢复最近一条,同时删除这条记录(推荐)

      复制代码
      git stash pop [序号]
    • 默认恢复最近一条,但保存暂存记录。

      复制代码
      git stash apply [序号]
  4. 删除暂存记录

    • 默认删除最近一条,可删除指定序号的记录。

      复制代码
      git stash drop [序号]
    • 清空所有暂存(谨慎操作)。

      复制代码
      git stash clear
4.3.1.3保存范围
会保存 默认不保存
已 add 加入暂存区的文件 未追踪的新建文件(需加 -u 参数)
工作区已修改文件 配置在 .gitignore 中的忽略文件
4.3.1.4规范与注意事项
  1. 团队协作、大厂规范:切换分支前保持工作区干净,未完成代码优先使用 stash 临时存放。

  2. 避免大量堆积无用 stash,定期清理,防止混淆。

  3. stash 仅本地生效,不会提交、不会同步远程。

  4. 恢复多条 stash 或跨分支恢复时,可能出现代码冲突,正常手动解决即可。

4.4合并分支(merge、rebase)

  1. 基本概念:把其它分支的代码合并到当前所在分支。

    复制代码
    git merge/rebase 其他分支名
  2. Merge 和 Rebase 是 Git 中两种完全不同的分支合并策略,没有绝对的好坏,只有适用场景的不同。

    • Merge:保留完整历史,产生合并提交,历史分叉。
    • Rebase:重写提交历史,无合并提交,历史线性。

4.4.1Merge

  1. 工作原理:Merge 会将两个分支的最新提交和它们最近的共同祖先进行三方合并,生成一个新的合并提交(Merge Commit),将两个分支的历史连接在一起

  2. 操作步骤:将 dev分支(A-B-C)merge 到 master 分支(A-D-E):

    复制代码
    # 1. 切换到目标分支(要合并到的分支)
    git checkout master
    
    # 2. 执行合并
    git merge dev
  3. 提交历史效果:

    复制代码
              D --- E --- F  master
             /         /
    A --- B --- C ---/
                    ^
                    dev
    1. 生成新的合并提交F :这是 merge 操作最核心的特征,它有两个父提交:E(master 原最新提交)和C(dev 最新提交)。
    2. 所有原始提交完整保留ABCDE的提交哈希和内容完全不变。
    3. 历史呈分叉状:可以清晰看到两个分支的完整开发轨迹和合并时间点。
    4. dev 分支完全不受影响 :dev 分支仍然指向提交C,没有任何变化。
    5. 冲突处理 :如果D/EB/C修改了同一文件的同一行,Git 会在生成F时提示冲突,需要手动解决后再提交
  4. 优点:

    1. 历史完整可追溯:能看到每个分支的开发轨迹和合并时间点。
    2. 操作安全简单:不会修改已有的提交历史,出错容易回滚。
    3. 冲突只解决一次:所有冲突集中在合并提交中一次性解决。
  5. 缺点:

    1. 提交历史杂乱:多人协作时会产生大量合并提交,历史线分叉严重,难以阅读。
    2. 排查问题困难:当出现 bug 时,大量的合并提交会增加二分查找(git bisect)的难度。

4.4.2Rebase

  1. 工作原理:Rebase 会找到两个分支的最近共同祖先,然后将当前分支的所有提交 "截取" 下来 ,临时保存为补丁,接着将当前分支指针移动到目标分支的最新提交上,最后将保存的补丁依次应用到这个新位置上

简单来说:把你的提交 "挪动粘贴" 到目标分支的最新提交后面

  1. 操作步骤:将 dev分支(A-B-C)rebase 到 master 分支(A-D-E):

    1. 切换到要变基的分支(你的开发分支)

    git checkout master

    2. 执行变基

    git rebase dev

  2. 提交历史效果:

    A --- B --- C --- D' --- E' master
    ^
    dev

  1. 重写 master 分支历史:没有生成新的合并提交,历史变成一条完美的直线。
  2. 原 master 提交被重写 :D → D'、E → E',提交内容完全不变,但提交哈希发生了改变
  3. 变基过程
  • Git 先找到两个分支的共同祖先A。
  • 临时保存 master 分支自A以来的所有提交(D、E)为补丁。
  • 将 master 分支指针移动到 dev 的最新提交C。
  • 依次将补丁D、E应用到C的后面。
  1. dev 分支完全不受影响:dev 分支仍然指向提交C,没有任何变化。
  2. 冲突处理:如果D和B/C有冲突,Git 会在应用D时暂停,解决冲突后执行git rebase --continue继续应用E;如果E也有冲突,需要再次解决。
  3. 如果想放弃变基,恢复到变基前的状态:git rebase --abort
  1. 优点:
    1. 提交历史整洁:没有多余的合并提交,历史线性,易于阅读和理解。
    2. 便于代码审查:PR/MR 中的提交记录清晰,每个提交都是独立的功能点。
    3. 便于后续操作:二分查找、回滚等操作更加简单高效。
  2. 缺点:
    1. 重写提交历史:会改变已有的提交哈希,存在一定风险。
    2. 冲突解决繁琐:如果有多个提交都有冲突,需要逐个提交依次解决。
    3. 操作相对复杂:新手容易出错,出错后回滚难度较大

4.4.3Merge VS Rebase

对比维度 Merge Rebase
提交历史 保留完整历史,产生合并提交,历史分叉 重写提交历史,无合并提交,历史线性
提交哈希 原有提交哈希不变 被变基的提交哈希全部改变
冲突处理 一次性解决所有冲突 逐个提交依次解决冲突
操作安全性 高,不修改已有历史,出错易回滚 中,修改已有历史,出错回滚较难
学习成本 低,简单易懂 高,需要理解变基原理
历史可读性 差,大量合并提交导致历史杂乱 好,线性历史清晰易读
对团队的影响 小,不会影响其他人的本地仓库 大,已推送到远程的提交禁止变基

4.4.4适用场景与最佳实践

  1. Merge使用场景:

    1. 合并公共主干分支 :将 dev 合并到 master,或者将 master 合并到 dev
    2. 多人协作的公共分支:所有团队成员都在使用的分支,必须保留完整的合并历史。
    3. 需要保留分支开发轨迹:当你需要明确知道某个功能是从哪个分支、在什么时间合并进来的时候。
  2. Rebase使用场景:

    1. 个人功能分支同步主干代码 :将 dev 的最新代码同步到你的 feature 分支。
    2. 提交 PR/MR 之前:整理你的提交历史,让代码审查更加顺畅。
    3. 本地未推送的提交:只在你自己的本地分支上使用,不要影响其他人
  3. 大厂通用规范:

    1. 公共主干分支(master/dev):永远使用 Merge。

      • 保留完整的合并轨迹,便于问题追溯和回滚。
      • 避免因变基导致的团队协作混乱。
    2. 个人功能分支:优先使用 Rebase。

      • 保持提交历史整洁,便于代码审查。
      • 每次拉取主干代码时使用 git pull --rebase 代替 git pull。
    3. Rebase 黄金法则(绝对不能违反)**:**永远不要对已经推送到远程仓库的提交执行变基操作!这会导致其他团队成员的本地历史与远程不一致,引发严重的协作混乱。。

4.5删除分支

不能删除当前分支,只能删除其它分支。及时清理不再需要的分支以保持仓库整洁!

  1. 安全删除分支(已合并才允许删除)。

    复制代码
    git branch -d 分支名
  2. 强制删除分支(无论是否合并)。

    复制代码
    git branch -D 分支名

5.Git远程操作

5.1创建远程仓库别名(add)

  1. 创建远程仓库别名。

    复制代码
    git remote add 远程仓库别名 <url>
    1. 远程仓库别名默认为origin,取决于远端服务器设置。
    2. 远程仓库地址,从远端服务器获取此url。
  2. 查看所有远程地址别名。

    复制代码
    git remote -v

5.2推送本地分支到远程仓库(push)

  1. 完整命令语法。

    复制代码
    git push [-f][-u/--set-upstream] [url/远程仓库别名 [本地分支名称][:远程分支名称]] 
    1. -f表示强制覆盖。
    2. -u表示建立起本地分支与远程分支的关联关系,后续推送操作可以省略远程仓库名称分支名称 ,使用git push即可推送当前所在的本地分支的最新提交关联的远程分支
    3. 一个本地分支只能关联一个远程分支,多次执行 -u 会更新关联关系。
  2. 远程分支与本地分支同名时可以只写一次分支名称(!!!推荐)

    复制代码
    git push -u origin 本地分支名称

    假设推送本地master分支到远程的origin/master分支。

    远程没有master分支(第一次推送) 远程已有master分支
    1.自动在远程 origin 仓库新建一个 master 分支 1.不会新建分支,直接将本地 master 的提交推送到远程已有的 master 分支
    2.将本地 master 分支的所有提交完整推送到远程 2.自动建立本地 master 与远程 origin/master 的上游关联关系
    3.自动建立本地 master 与远程 origin/master 的上游关联关系 3.如果有冲突,会提示先拉取远程代码解决冲突后再推送

5.3拉取/提取远程分支到本地仓库(fetch、pull)

5.3.1提取远程分支代码(fetch)

  1. 提取指定远程分支的最新提交,只更新对应的远程跟踪分支,不碰任何本地代码和分支。

    复制代码
    git fetch [url/远程仓库别名 [远程分支名称]]

    git fetch origin dev 的执行效果:

    1. 提取远程 origin 仓库 dev 分支的最新提交。
    2. 更新本地的远程跟踪分支 origin/dev (这是 Git 自动维护的,名称永远是 origin/远程分支名,不能自定义)。
    3. 不创建、不修改任何普通本地分支。
  2. fetch常用写法:提取所有远程分支的最新提交(!!!推荐)

    复制代码
    git fetch [url/远程仓库]
  3. fetch后的后续操作:拉取完成后,需要手动将远程更新合并到本地分支。

    复制代码
    git checkout dev //切换到本地dev分支
    
    # 方式1:合并方式(推荐公共分支使用)
    git merge origin/dev
    
    # 方式2:变基方式(推荐个人分支使用)
    git rebase origin/dev

5.3.2拉取远程分支代码(pull)

  1. 自动合并远程代码到当前本地分支。

    复制代码
    git pull [--rebase] [url/远程仓库别名 [远程分支名称][:本地分支名称]] 
    1. -rebase:使用 变基(Rebase)方式合并远程代码,替代默认的合并(Merge) 方式,不会产生额外的合并提交记录。
    2. 若本地分支已与远程分支建立关联关系,后续拉取操作可以省略远程仓库名称分支名称 ,使用git pull即可拉取当前所在的本地分支所关联的远程分支的最新提交
  2. 远程分支与本地分支同名时可以只写一次分支名称(!!!推荐)

    复制代码
    git pull origin 远程分支名称 

5.3.3 Git pull和Git fetch的核心区别

操作 执行内容 对本地分支的影响 适用场景
git pull git fetch + git merge(或git rebase 自动合并远程代码到本地当前分支 确定要将远程更新合并到本地时使用
git fetch 仅拉取远程更新,不合并 仅更新远程跟踪分支,本地工作区不变 只想查看远程更新,暂时不想合并时使用

5.4克隆远程仓库到本地(clone)

  1. 克隆远程仓库到本地。

    复制代码
    git clone <url> [本地目录] //克隆到指定名称的本地目录,而不是默认的仓库名
    git clone -b 远程分支名 <url> //只克隆指定分支,不下载其他分支的历史
    git clone --depth 1 <url> //浅克隆,只下载最新一次提交,速度快(不包含完整历史)
  2. 克隆的完整执行步骤:

    1. 创建本地目录:以远程仓库名命名,在当前路径下新建一个空目录。
    2. 初始化本地仓库:在该目录中执行 git init,创建 .git 隐藏文件夹。
    3. 添加远程仓库别名:自动为远程仓库添加默认别名 origin(等价于 git remote add origin )。
    4. 拉取完整远程代码:下载远程仓库所有分支的所有提交历史和代码。
    5. 创建所有远程跟踪分支:在本地生成 origin/master、origin/dev 等所有远程分支的本地镜像。
    6. 自动创建并切换到默认分支:创建与远程默认分支(通常是 main 或 master)同名的本地分支,并自动切换到该分支。
    7. 自动建立上游关联关系:将本地默认分支与远程默认分支绑定(等价于 git branch -u origin/master)。
  3. 注意事项:

    • git clone 只会为远程仓库的「默认分支」(通常是 main 或 master)自动创建本地分支并建立上游关联。其他所有远程分支,Git 只会在本地生成远程跟踪分支(如 origin/dev),不会自动创建对应的本地分支,更不会建立关联
    • 当你执行 git checkout 分支名 时,如果本地没有这个分支,但远程有同名分支,Git 会自动:
      • 创建同名本地分支,自动切换到该分支。
      • 自动建立与远程分支的上游关联。
相关推荐
恋喵大鲤鱼2 小时前
git fetch
git·git fetch
Java知识技术分享2 小时前
安装sourcetree
java·git·源代码管理
恋喵大鲤鱼3 小时前
git revert
git·git revert
爱和冰阔落3 小时前
【Codex项目实战】从模糊需求到可验证交付:Plan、测试、Review与Worktree完整流程
人工智能·git·codex
恋喵大鲤鱼13 小时前
git rebase
git·git rebase
大志哥12317 小时前
idea+git插件+云备份实现项目新分支新建维护
git
恋喵大鲤鱼18 小时前
git merge
git·git merge
码客日记18 小时前
Spring Boot 配置文件敏感信息加密(Jasypt 企业级完整方案)
java·spring boot·git
_codemonster18 小时前
Codex 核心进阶玩法(技能/MCP/派生/分叉/Git/钩子/子智能体)
git