拾忆🍂拾忆🍂
  • cpp
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • 百变小组件
  • hdc
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • Git
  • Nginx
  • Ollama
  • Adobe Audition
  • Aseprite
  • Excel
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • cpp
  • MySQL
  • Oracle
  • PostgreSQL
  • MyBatis
  • API升级
  • HMOS
  • 百变小组件
  • hdc
  • 元服务
  • Java
  • MinIO
  • Stream
  • JSP & Struts2
  • Spring
  • FFmpeg
  • Linux
  • Git
  • Nginx
  • Ollama
  • Adobe Audition
  • Aseprite
  • Excel
  • Markdown基本用法
  • MuseScore 4.x
  • UVR
  • Windows
  • emoji-cheat-sheet
  • IDE快捷键
  • obs-studio
  • YOLO
  • Python
  • VuePress 2.x
  • 内置组件
  • markdown-container
  • markdown-ext
  • markdown-hint
  • markdown-preview
  • markdown-tab
  • Markdown扩展语法
  • 插件配置
  • prismjs
  • 样式
  • CSS
  • JS
  • TS
  • Vue3
主页
梦的开始🌅
  • 「从开始,到永久」
  • C艹

    • cpp
  • Database

    • MySQL
    • Oracle
    • PostgreSQL
    • MyBatis
  • HarmonyOS

    • API升级
    • HMOS
    • 百变小组件
    • hdc
    • 元服务
  • Java

    • Java
    • MinIO
    • Stream
    • JSP & Struts2
    • Spring
  • Linux

    • FFmpeg
    • Linux
    • Git
    • Nginx
  • LLM

    • Ollama
  • Others

    • Adobe Audition
    • Aseprite
    • Excel
    • Markdown基本用法
    • MuseScore 4.x
    • UVR
    • Windows
    • emoji-cheat-sheet
    • IDE快捷键
    • obs-studio
    • YOLO
  • Python

    • Python
  • VuePress

    • VuePress 2.x
    • 内置组件
    • markdown-container
    • markdown-ext
    • markdown-hint
    • markdown-preview
    • markdown-tab
    • Markdown扩展语法
    • 插件配置
    • prismjs
    • 样式
  • Web

    • CSS
    • JS
    • TS
    • Vue3
  • 主页

Git

本地修改了分支-远程分支已有新提交-如何拉取🌸

暂存后拉取

  1. 提交本地更改:

    使用 git add 和 git commit 将本地更改提交到本地仓库。确保本地代码没有未提交的更改。

  2. 拉取远程分支:

    # your_branch_name 更改为本地分支名称(如 master/main/develop)
    git pull origin <your_branch_name>
    
  3. 解决冲突:

    如果在执行 git pull 时发生冲突,Git 会提示你解决冲突。手动解决冲突并保存修改。

  4. 提交合并:

    一旦冲突解决完毕,使用 git add 命令将解决后的文件添加到暂存区,并使用 git commit 提交合并的更改。

  5. 推送到远程分支:

    git push origin <your_branch_name>
    

使用 git stash

如果本地想在不执行commit的情况下拉取远程最新提交,需要使用 git stash 储藏工作区修改,再执行拉取操作,最后恢复修改。

  1. 储藏本地修改

    git stash push -m "暂存本地修改(不包含未跟踪文件)"
    
    • git stash push:将工作目录和暂存区的修改保存到“储藏栈”中,工作区会恢复到上次提交的干净状态。
    • -m "描述":可选,添加备注便于识别(推荐使用)。
  2. 拉取远程最新提交

    # your_branch_name 更改为本地分支名称(如 master/main/develop)
    git pull origin <your_branch_name>
    
    • 此时工作区无本地修改,可安全拉取远程最新代码。
  3. 恢复本地修改

    git stash pop
    
    • 将最近一次储藏的修改恢复到工作区,并自动删除该储藏记录(若有冲突则不会自动删除)。
    • 若恢复时发生冲突(文件被远程修改且本地也修改了),需手动解决冲突(冲突文件会包含 <<<<<<< 标记)。

    重要

    当执行 git stash pop 时,Git 会尝试将暂存的修改应用到当前工作目录。文件会有以下状态:

    四种状态

    1. Auto-merging
      • 含义: 表示 Git 成功自动合并 这些文件。远程和 stash 中的修改互不干扰,Git 能够自动将这些修改合并。
      • 举例: stash 中的一个文件,修改了第10行;git pull 下来的版本修改了第20行。这两处修改 Git 就会自动合并。
    2. Changes to be committed
      • 含义: 这表示在您执行 git stash 时,有些修改已经使用 git add 添加到了暂存区。在 pop 之后,这些修改被成功地、自动地恢复到了暂存区状态,等待您提交。
      • 举例: 先修改了 a.txt 并 git add 了它,然后执行了 git stash。当 pop 时,这个对 a.txt 的修改就会直接出现在暂存区,而不是工作区。
    3. Unmerged paths
      • 含义: 这是最关键的一项。表示 发生了合并冲突。有些文件在 stash 的版本和 git pull 后的当前版本中,对 相同的位置 进行了修改,Git 无法自动决定该保留哪个修改,因此需要手动解决这些冲突。
      • 文件状态: 这些文件会被标记为 both modified。
      • 处理方式: 您需要打开这些文件,解决标记为 <<<<<<<, =======, >>>>>>> 的冲突部分,然后使用 git add 命令将解决后的文件标记为已解决。
    4. Untracked files
      • 含义: 这表示在您执行 git stash 时,工作目录中存在一些新增的、未被Git跟踪的文件。默认的 git stash 不会保存这些未跟踪文件(除非使用 git stash -u 或 -a 选项)。这里的提示可能是在告诉您这些文件依然存在,或者是从 stash 中恢复出来的(如果您用了 -u)。

    当发生冲突时

    存在 Unmerged paths(合并冲突),apply 操作被认为是没有“完全成功”的。Git 出于安全考虑,中断了自动删除的步骤,并给您留下了提示:

    警告

    "The stash entry is kept in case you need it again."

    这是由于:git stash pop 在应用存储时遇到了合并冲突不会自动删除 stash 。

    这个命令实际上是两个操作的组合:

    1. git stash apply: 尝试将存储的修改应用到当前工作目录。
    2. git stash drop: 只有在 apply 成功完成(没有产生任何冲突)的情况下,才会自动删除对应的存储条目。

    在您的情况下,由于存在 “Unmerged paths” (合并冲突),apply 操作被认为是没有“完全成功”的。Git 出于安全考虑,中断了自动删除的步骤,并给您留下了提示:

    这样做的目的是:

    • 给您一个回退的机会: 如果您在解决冲突的过程中搞砸了,或者想放弃这次合并,您可以通过 git stash apply 重新应用这个被保留的 stash,或者使用 git checkout 来撤销对冲突文件的修改,然后换个方式重新尝试。
    • 防止数据丢失: 在冲突完全解决之前,Git 无法确定您的最终意图,因此它选择保留原始的存储内容,确保您的工作成果不会因为一次失败的自动合并而丢失。

⚠️ 关键注意事项

  1. 未跟踪文件(Untracked Files)

    git stash 默认不保存未跟踪文件(如新创建未 git add 的文件)。若需保存,使用:

    git stash push -u -m "暂存所有修改(含未跟踪文件)"
    

    -u 参数会包含未跟踪文件。

  2. 多批次储藏

    可多次执行 git stash push 保存多组修改,通过 git stash list 查看记录。恢复时用:

    git stash pop stash@{0}  # 恢复指定储藏(0 为栈索引)
    
  3. 冲突处理

    若 git stash pop 后出现冲突:

    • 手动编辑冲突文件(搜索 <<<<<<< 标记)。
    • 解决后执行 git add 冲突文件名 标记为已解决。
    • 最后 git stash drop 删除储藏记录(pop 失败时需手动删除)。
  4. 替代方案(谨慎使用)

    git commit -am "临时提交"  # 将修改临时提交
    git pull --rebase         # 变基拉取(将临时提交置于最新提交之上)
    git reset HEAD~1          # 撤销临时提交,保留修改在工作区
    
    • 适用于熟悉 rebase 的用户,操作更复杂但可避免储藏栈管理。

💡 操作流程图解

冲突处理

  1. 查看冲突文件状态,查看被标记为冲突(Unmerged paths) 的文件

    git status
    
  2. 手动解决文件冲突

    • 用编辑器打开冲突文件:

      code src/lib/components/layout/Sidebar/UserMenu.svelte
      
    • 在文件中查找冲突标记:

      <<<<<<< Updated upstream
      // 以下是远程版本的代码(来自最新拉取的提交)
      // 远程修改内容...
      =======
      // 以下是您本地修改的代码(来自 stash)
      // 本地修改内容...
      >>>>>>> Stashed changes
      
    • 手动编辑文件:选择保留远程版本/本地版本,或合并两者,并删除所有冲突标记:<<<<<<<、=======、>>>>>>>。

  3. 标记冲突已解决

    # 此命令告知 Git 该文件冲突已解决
    git add src/lib/components/layout/Sidebar/UserMenu.svelte
    
  4. 完成 stash 恢复

    重要

    再此之前应该先执行 git status 确认冲突文件已经全部解决。

    git stash drop
    
    • 手动删除被保留的 stash 条目(因为 pop 未自动完成,Git 不会自动删除最近一条 stash 记录。)
    • 使用 git stash list 可查看所有储藏记录。

恢复工作区更改

在使用 git stash pop 恢复储藏区更改遇到冲突之后,仓库处于混合状态:

  • 已应用:stash 中的部分修改
  • 冲突中(如果有):与远程更新冲突的文件
  • 已更新:git pull 成功拉取的远程内容

使用 git restore 放弃对已追踪文件的修改(推荐)Git 2.23+ 引入

# 恢复所有文件到最新一次提交的状态
git restore .

# 重新应用最新的一次 `stash`
git stash apply stash@{0}
  • . 表示当前目录

提示

传统命令(Git 1.6.0+)

git checkout -- .
  • -- 是一个分隔符,表示"后面是文件路径,而不是分支名"
  • . 表示当前目录

使用 git reset 撤销恢复(不推荐)

重要

放弃当前冲突恢复(恢复工作区到执行 git stash pop 之前的状态),它彻底清除了工作目录和暂存区中所有未提交的更改。这包括:

  • 执行 stash pop 之前已经存在于工作目录但尚未提交的本地修改。
  • stash pop 操作试图应用的来自暂存区的修改。
  • stash pop 操作产生的所有冲突标记。
git reset --hard HEAD

# 重新应用 `stash`
git stash apply stash@{0}

冲突预防建议:

# 下次 `stash` 时添加详细描述
git stash push -m "修改描述_日期"

# 拉取前检查差异
git diff origin/main...HEAD  # 替换 main 为您的分支名

上传本地代码到 GitHub

  1. 在 GitHub 上创建仓库:

    • 打开 GitHub 网站,登录你的账号。
    • 点击页面右上角的加号图标,选择 "New repository"(或类似选项)。
    • 输入仓库名称、描述和其他设置,并选择公开或私有仓库。
    • 点击 "Create repository" 创建新的远程仓库。
  2. 初始化本地仓库:

    • 在你的本地计算机上,进入你想要上传到 GitHub 的项目文件夹。
    • 打开命令行终端。
  3. 初始化 Git 仓库:

    • 执行 git init 命令来初始化一个新的 Git 仓库。
  4. 添加远程仓库链接:

    • 执行 git remote add origin <remote_repository_url> 命令,将你在 GitHub 上创建的远程仓库链接与本地仓库关联。
      • <remote_repository_url>:仓库的 HTTPS 或 SSH 链接。
  5. 添加和提交代码:

    • 执行 git add . 命令将所有本地文件添加到暂存区。
    • 执行 git commit -m "Initial commit" 命令将暂存区的更改提交到本地仓库。你可以自定义提交信息以描述本次提交的内容。

    重要

    1. 如果远程仓库有初始化好的README.md等文件,先拉取仓库最新文件:

      • 使用 git fetch origin master 拉取远程仓库代码

      • 使用 git merge origin/master 合并远程 master 分支到本地 master 分支

      • 如果你希望将远程 origin/master 分支的更改合并到一个新的本地分支,可以使用以下命令:git checkout -b new_branch origin/master

    2. 重新执行第5步

  6. 推送到远程仓库:

    • 运行 git push -u origin master(如果你的主分支是 master)将本地仓库的代码推送到远程仓库。

      提示

      • -u 参数是 --set-upstream 的简写。

      • 设置上游分支关联:将本地的 master 分支与远程的 origin/master 分支建立跟踪关系

      • 简化后续操作:设置关联后,以后执行 git push 和 git pull 时就不需要指定远程仓库和分支名了

git command list✨

好的,以下是修改后的Git命令表格,使用<>和[]括住需要参数的部分:

命令命令示例详细解释
git initgit init在当前目录初始化一个新的Git仓库
git clone <repository_url>git clone https://github.com/user/repo.git克隆远程仓库到本地
git add <file_path>git add file.txt将文件添加到暂存区
git commit -m "<commit_message>"git commit -m "Add new feature"将暂存区的内容提交到本地仓库
git statusgit status显示工作树的状态
git push <remote_name> <branch_name>git push origin master将本地仓库的内容推送到远程仓库
git pull <remote_name> <branch_name>git pull origin master从远程仓库拉取内容到本地仓库
git branchgit branch显示本地分支列表
git checkout <branch_name>git checkout main_branch切换到指定分支
git merge <branch_name>git merge feature_branch将指定分支合并到当前分支
git remotegit remote显示远程仓库的别名列表
git fetch <remote_name>git fetch origin从远程仓库获取最新内容,但不合并到本地仓库
git loggit log显示提交历史记录
git reset <commit_hash>git reset commit_hash将HEAD指针指向特定的提交,可选地重置暂存区和工作树
git revert <commit_hash>git revert commit_hash创建一个新的提交,撤销指定提交的更改
git stashgit stash push -m "暂存本地修改"
git stash pop
将当前工作树中的变更保存到堆栈中,以便稍后恢复
git cherry-pick <commit_hash>git cherry-pick commit_hash选择一个特定的提交并将其应用到当前分支
git remote add <remote_name> <repository_url>git remote add origin https://github.com/user/repo.git添加远程仓库别名
git remote remove <remote_name>git remote remove origin移除指定的远程仓库别名
git diffgit diff显示暂存区和工作树之间的差异
git diff <commit_old_hash> <commit_new_hash>git diff 343e12b1 ad494be0 --stat查看new相对于old提交之间的差异,加上 --stat 参数则只输出统计信息;
git tag <tag_name>git tag v1.0.0创建一个新的标签
git push --tagsgit push --tags将本地标签推送到远程仓库
git config --global <config_param> "<config_value>"git config --global user.name "John Doe"配置Git的全局设置
git log --graphgit log --graph以图形方式显示提交历史记录
git clean [-n]git clean -n显示将要删除的未跟踪文件列表,使用-f进行实际删除
git rm <file_path>git rm file.txt从Git中删除文件
git show <commit_hash>git show commit_hash显示特定提交的详细信息
git rebase <branch_name>git rebase main_branch将当前分支的更改在指定分支上重新应用

请注意,尖括号<>表示必需参数,而方括号[]表示可选参数。这样更容易理解每个Git命令所需的参数。

在命令行参数符号意思

  1. <> 尖括号:

    • 一般代表命令必填参数,即在执行命令时必须提供的参数。
    • 示例:command <required_parameter>
  2. [] 方括号:

    • 一般代表命令可选参数,即在执行命令时可以选择性地提供的参数,但不是必需的。
    • 示例:command [optional_parameter]
  3. {} 花括号:

    • 有时也用于表示命令必填参数,与尖括号类似。这种用法可能因具体的命令规范而异。
    • 示例:command {required_parameter}
  4. () 圆括号:

    • 圆括号在命令行中通常用于表示一组选项,用户可以从中选择一个。
    • 示例:command (option1 | option2 | option3)
  5. | 管道符号:

    • 管道符号用于将一个命令的输出作为另一个命令的输入。不表示参数本身,但是在命令行操作中很常见。
    • 示例:command1 | command2
  6. ... 省略号:

    • 省略号表示参数可以重复出现多次。
    • 示例:command <required_parameter> ...

远程分支名称解析

在 Git 中,远程分支名称如 origin/main 的命名规则和本地分支 main 的关系,是由 Git 的分支管理机制决定的,核心原因在于 命名空间隔离 和 远程跟踪分支(Remote-Tracking Branch) 的设计。以下是详细解释:

1. 为什么远程分支叫 origin/main?

  • origin 是远程仓库的别名:
    当你克隆仓库时,Git 默认将远程仓库命名为 origin(可自定义)。origin 代表远程仓库的 URL 地址。
  • 斜杠 / 是命名空间分隔符:
    origin/main 表示“远程仓库 origin 上的 main 分支”。斜杠的作用是:
    • 避免本地分支与远程分支同名冲突(例如本地可同时存在 main 和 origin/main)。
    • 明确标识分支的来源(远程仓库名 + 分支名)。

2. 为什么拉取后本地分支叫 main?

  • 远程跟踪分支(Remote-Tracking Branch):
    origin/main 是一个本地存在的引用,它记录远程仓库 origin 上 main 分支的最新状态。它不是真正的本地分支,而是 Git 在本地创建的“影子分支”,用于跟踪远程变化。
  • 创建本地分支:
    当你运行 git checkout main(或 git switch main)时,Git 会:
    1. 查找本地是否存在 main 分支。
    2. 若不存在,则自动基于 origin/main 创建同名的本地分支 main,并建立跟踪关系(Tracking Relationship)。
    # 示例:拉取远程 main 分支到本地
    git checkout main  
    # 等价于:git checkout -b main --track origin/main
    

3. 关键概念解析

类型名称示例作用
远程仓库别名origin指向远程仓库 URL 的简称(默认为 origin)
远程跟踪分支origin/main本地存储的远程分支状态,只读(通过 git fetch 更新)
本地分支main用户实际操作的开发分支,可提交代码
跟踪关系(Tracking)main → origin/main本地分支与远程分支的关联,git pull/git push 无需指定远程分支

4. 设计目的与优势

  • 隔离性:
    远程分支(origin/main)和本地分支(main)物理分离,防止误操作覆盖远程分支。
  • 清晰的状态管理:
    • git status 会提示本地分支与 origin/main 的提交差异(例如领先或落后)。
    • git branch -a 可同时查看本地分支和远程跟踪分支(以 remotes/origin/ 开头)。
  • 简化协作流程:
    通过跟踪关系,git pull = git fetch(更新 origin/main) + git merge origin/main(合并到本地分支)。

5. 常见操作示例

  • 查看远程跟踪分支:
    git branch -r  # 显示所有远程跟踪分支(如 origin/main)
    
  • 手动建立跟踪关系:
    git branch -u origin/main  # 将当前本地分支跟踪到 origin/main
    
  • 删除远程跟踪分支(当远程分支已删除):
    git fetch origin --prune  # 清理本地失效的远程跟踪分支
    

总结

  • origin/main 是 Git 在本地创建的远程跟踪分支,用于记录远程仓库状态,命名格式为 <远程仓库名>/<分支名>。
  • main 是用户操作的本地分支,通过 git checkout 基于 origin/main 创建并自动建立跟踪关系。
  • 斜杠 / 是 Git 的命名约定,确保本地与远程分支的命名空间互不冲突。

这种设计既保证了远程分支状态的独立性,又简化了本地开发流程,是 Git 分布式架构的核心特性之一。

——————————

文件状态

在Git中,文件的状态可以分为以下几种:

  1. 未跟踪(Untracked):文件是新的,Git之前没有跟踪过。
  2. 已修改(Modified):文件被修改了,但还没有被暂存(unstaged changes)。
  3. 已暂存(Staged):文件被修改并且已经通过 git add 命令添加到了暂存区,等待提交。
  4. 未修改(Unmodified):文件没有修改,或者修改已经被提交。

在 VS Code 的 Git 窗口中,文件被分为 "Staged Changes" 和 "Changes" 两类,这是 Git 工作流程的核心设计,具体区别如下:

  1. Changes(未暂存的修改)

    • 含义:文件已被修改(或新增),但尚未添加到 Git 的暂存区(Staging Area)。
    • 状态特点:
      • 文件处于工作目录(Working Directory)中。
      • 这些修改不会被包含在下一次 git commit 中。
      • 在 VS Code 中显示为 "Changes" 分组(通常位于顶部)。
    • 操作建议:
      • 点击文件旁的 "+" 图标 或右键选择 "Stage Changes" 可将其移至暂存区(相当于 git add)。
      • 直接编辑文件会导致此分组动态更新。
  2. Staged Changes(已暂存的修改)

    • 含义:文件已通过 git add 添加到暂存区,准备被提交。
    • 状态特点:
      • 文件已进入 Git 的暂存区(Index)。
      • 这些修改会被包含在下一次 git commit 中。
      • 在 VS Code 中显示为 "Staged Changes" 分组(位于 "Changes" 下方)。
    • 操作建议:
      • 点击文件旁的 "-" 图标 或右键选择 "Unstage Changes" 可移回未暂存状态(相当于 git restore --staged)。
      • 点击 √ 提交按钮 会提交此分组的所有文件。

⚙️ 设计目的:精准控制提交内容

Git 通过分离 工作目录 → 暂存区 → 版本库 的三级流程,实现:

  • 选择性提交:仅暂存部分文件(如只提交功能 A 的代码,暂不提交调试日志)。
  • 分批提交:将大改动拆解为多个逻辑独立的提交。
  • 减少误提交:避免未完成的修改意外进入版本历史。

💡 VS Code 操作对比表

状态VS Code 显示分组操作等效 Git 命令
未暂存的修改Changes点击 +git add <file>
已暂存的修改Staged Changes点击 -git restore --staged <file>

提示

示例场景

假设你修改了 a.js 和 b.js:

  1. 初始状态 → 两文件均显示在 "Changes" 分组。
  2. 点击 a.js 旁的 "+" → a.js 移动到 "Staged Changes"。
  3. 点击提交按钮 → 仅提交 a.js,b.js 仍保留在未暂存状态。

Repo

Repo 基于git的工具,它用来管理多个git代码库。把所有的代码用一个git库管理已经越来越力不从心。这个时候的一个很自然的思路就是分而治之,把整个project按模块分成一个个单独的git库,再用一个统一的工具管理,repo因此应运而生。

规范

常用 Commit 标签描述

标签描述示例
feat新功能feat: 添加用户注册端点
fix修复 bugfix: 修复首页数据无法加载的问题
docs仅文档更改docs: 更新 API 接口文档
style代码风格调整(不影响代码运行)style: 修正变量命名缩进
refactor代码重构(既非新功能,也非修 bug)refactor: 使用策略模式重构支付逻辑
perf性能优化perf: 使用 memo 缓存组件减少重复渲染
test添加或修改测试用例test: 为用户服务添加单元测试
build影响构建系统或外部依赖的更改build: 升级 webpack 到 v5
ci持续集成配置和脚本的更改ci: 在 GitHub Actions 中增加 SonarQube 检查
chore其他不修改源码或测试文件的杂项变更chore: 更新依赖包版本
revert回滚之前的提交revert: 回滚提交 abc123

例如:

feat: 添加用户登录功能

- 实现用户名密码登录
- 添加记住密码功能
- 优化登录错误提示

Closes #123

命令

查看待commit的文件路径

待commit:已添加到暂存区

git diff --name-only --cached

提示

命令执行之后

  • 键入:q 退出命令
  • 键入:s 输入文件名称保存到项目根路径

git pull 和 git fetch 区别

提示

先总结:

  • git pull 是从远程仓库获取最新代码并 直接合并 到当前分支的操作。
  • git fetch 是仅从远程仓库获取最新代码但 不进行合并 的操作。
具体区别
  1. git pull:

    • git pull = git fetch + git merge 。

      # 假设远程仓库别名为origin 分支名为main
      git pull origin main
      
      # 相当于
      git fetch
      git merge origin/main
      
    • 如果有冲突,你需要解决冲突后才能完成合并。

    • git pull 的执行过程会直接更新当前分支的工作目录。

  2. git fetch:

    • git fetch 从远程仓库获取最新的提交记录和分支信息,但不会将这些更改直接合并到当前分支。
    • 它只会将获取的远程分支更新到本地仓库的 .git 目录下,而不会修改工作目录中的文件。
    • git fetch 可以帮助你了解远程仓库的最新状态,你可以通过查看远程分支来了解它的提交记录,然后决定是否要进行合并操作。

git merge

将远程分支的更新合并到当前的分支,需要手动执行 git merge 或者其他合并命令(例如 git rebase)来将这些更新应用到你的工作目录和分支。

下面是一种常见的步骤来将远程分支的更新合并到你当前的分支:

  1. git fetch: 从远程仓库获取最新提交记录和分支信息。
  2. git merge origin/your_remote_branch: 将远程分支合并到你当前的分支。your_remote_branch 是你想合并的远程分支的名称。这个命令会将远程分支的更改合并到你的当前分支中。

或者,如果你喜欢使用 git pull,你也可以用 git pull 命令来达到相同的目的,因为 git pull 实际上包含了 git fetch 和 git merge 的操作:

git pull origin your_remote_branch

无论是使用 git fetch 和手动 git merge,还是直接使用 git pull,都要确保在执行合并操作之前没有未提交的更改,以免可能产生冲突。如果有冲突,你需要先解决冲突后再提交合并的更改。

git stash

当需要 切换到其他分支 或 本地已经做了修改需要拉取远程代码 时,不希望携带当前工作区内未commit的内容时,stash就派上了用场,它可以储藏当前未commit的数据。

重要

在 Windows 终端或某些 shell 中,stash@{0} 中的花括号 {} 可能被错误解析。实际使用时,可以直接使用数字索引,Git2.11.0+(2016-11-29发布) 会自动识别。只需要键入 index 对应的阿拉伯数字即可。另外提供老版本兼容办法:

  • 可以使用 ^ 号进行转义:stash^@{index}
  • 加双引号:"stash@{index}"

注:最近一次 stash 记录的 index 值总是 0 。

例如:

>git stash list
stash@{0}: On main: 版本2 # 最近 `stash` 的记录
stash@{1}: On main: 版本1 # 最早 `stash` 的记录

# 查看stash{0}与当前工作区的详细行变更
## `-p` 参数表示以补丁格式显示,包含具体的代码变更
> git stash show -p 0

用法:

  • 储藏工作区内的修改,并给此次 stash 命名

    git stash push -m '暂存提交'
    

    重要

    如果需要包含以下三种文件,使用 -u 选项:

    • 已暂存文件(已经 git add 过的)
    • 未暂存文件(工作区内修改)
    • 未跟踪文件(刚新增还未跟踪的文件)
    git stash push -m '暂存提交' -u
    

    提示

    对比 git stash save 的优势?

    git stash push 支持一个非常重要的特性:路径限定符 -- <pathspec>。这允许你只暂存工作目录中特定文件或路径的更改,而不是整个工作目录。例如:

    git stash push -m "暂存src/的修改" -- src/
    git stash push -m "暂存file.txt" -- file.txt
    
  • 查看所有的 stash

    git stash list
    
  • 查看特定的 stash

    git stash show -p stash@{index}
    
    # 例如
    git stash show -p 0
    
    • -p:以补丁格式显示,包含具体的代码变更。(不加则仅查看改动了几个文件,一共新增/删除多少行,类似 git diff --stat )
  • 恢复最近一次储藏的修改,并将其从 stash 列表中移除

    git stash pop
    

    重要

    相当于

    # 恢复最新的储藏,并在成功恢复之后删除它。
    git stash apply && git stash drop
    

    如果恢复发生了冲突,Git不会自动删除这个stash,需要手动进行冲突处理。

  • 恢复特定的 stash

    git stash apply stash@{index}
    
  • 删除特定的 stash,但不会恢复其中的修改

    git stash drop stash@{index}
    # 例如
    git stash drop 0
    
  • 删除所有暂存的 stash

    git stash clear
    

git diff

用于比较 Git 仓库中不同版本、文件或分支之间差异的核心命令。

  1. 比较工作区与暂存区
  • 查看已修改但未暂存(未 git add)的文件内容变化:
    git diff
    
  1. 比较暂存区与最新提交
  • 查看已暂存但未提交(已 git add)的更改:
    git diff --staged
    # 或
    git diff --cached
    
  1. 比较两个提交之间的差异
  • 指定两个提交的哈希值或引用:
    git diff <commit1> <commit2>
    
  1. 比较分支之间的差异
  • 查看两个分支的最新提交差异:
    git diff <branch1> <branch2>
    
  • 比较当前分支与另一分支:
    git diff <branch_name>
    
  1. 比较特定文件的更改
  • 限定只查看某个文件的差异:
    git diff <file_path>
    
  • 跨分支比较指定文件:
    git diff <branch1> <branch2> -- <file_path>
    
  1. 其他常用选项
  • 统计变更摘要(增/删行数):
    git diff --stat
    
  • 显示单词级差异(而非行级):
    git diff --word-diff
    

提示

输出格式说明

  • --- 表示原始文件,+++ 表示修改后的文件。
  • - 开头的行:被删除的内容。
  • + 开头的行:新增的内容。
  • 上下文行(无符号):未更改的代码,用于定位变更位置。
  • 冲突标记:查看第2条内容

代理

配置代理

# Set HTTP proxy
git config --global http.proxy "http://127.0.0.1:7890"

# Set HTTPS proxy
git config --global https.proxy "http://127.0.0.1:7890"

# 验证
git config --get http.proxy
git config --get https.proxy

取消代理

# Unset HTTP proxy
git config --global --unset http.proxy

IDEA的 Update Project

场景一:默认/使用 Merge 方式更新

相当于:;这是最传统、最安全的方式。

执行的 Git 指令序列大致如下:

  1. git fetch origin
    • 这是最关键的一步。它从远程仓库(通常是 origin)获取所有最新的分支、标签信息,但不会自动合并到你的当前工作分支。它只是让你本地知道远程仓库现在是什么样子。
  2. git merge origin/your-current-branch-name (例如 git merge origin/main)
    • 在 fetch 获取到远程的最新信息后,IDEA 会将远程分支(origin/main)合并 到你当前检出的本地分支(main)。

简单来说,Merge 方式 = git fetch + git merge

结果: 如果远程有新的提交,你的本地分支会生成一个额外的 合并提交,将两条开发线汇合。

场景二:使用 Rebase 方式更新

这是一种更线性和整洁的更新方式,也是目前很多团队推荐的做法。

执行的 Git 指令序列大致如下:

  1. git fetch origin
    • 同样,第一步永远是先获取远程的最新信息。
  2. git rebase origin/your-current-branch-name (例如 git rebase origin/main)
    • 在 fetch 之后,IDEA 不是执行合并,而是执行 变基。它会将你本地尚未推送到远程的提交“暂时取下”,然后基于远程最新的提交重新应用你的提交。

简单来说,Rebase 方式 = git fetch + git rebase

结果: 你的本地提交会“移动”到项目最新提交的顶端,形成一条直线式的历史,没有合并提交。

如何查看和配置更新类型?

在 IDEA 中,路径是:
File -> Settings -> Version Control -> Git
在右侧找到 Update Method 进行选择。

  • Merge: 默认选项。
  • Rebase: 更干净的提交历史。
  • Branch Default: 使用为该分支配置的默认策略。

特殊情况下的行为

  • 如果当前分支有未提交的更改:
    IDEA 非常智能,它不会直接执行 merge 或 rebase,因为这会与未提交的更改冲突。它会先尝试 Stash(储藏) 你的更改。
    • 相当于执行:git stash push -m "IDEA Stash before Update"
    • 然后执行 git fetch + git merge/rebase
    • 最后再尝试 Unstash(应用储藏):git stash pop
    • 如果应用储藏时发生冲突,IDEA 会提示你解决冲突。
  • 如果当前分支在远程没有对应的上游分支:
    IDEA 的 Update Project 按钮可能会变灰或无法正常工作,因为它不知道要和哪个远程分支进行同步。

总结对比

特性Merge 方式Rebase 方式
等效命令git fetch + git mergegit fetch + git rebase
提交历史保留合并提交,呈网状线性整洁,像一条直线
安全性较高,不重写历史较低,重写了本地提交历史
适用场景公共分支(如 main/master),团队新手友好个人功能分支,追求清晰历史

多Remote

(一个本地项目,关联两个远程仓库)

1. 准备本地仓库

可以用现有仓库,也可以新建一个:

git init

如果已经连接了 GitHub 或其他远程,执行:

git remote -v

会看到类似输出:

origin  git@github.com:username/repo.git (fetch)
origin  git@github.com:username/repo.git (push)

2. 添加第二个远程仓库

假设第二个远程是 GitLab,远程名可以自定义,常见如 origin2 或 gitlab,这里用清晰的 gitlab :

git remote add gitlab git@gitlab.com:username/repo.git

再次查看:

git remote -v

输出会是:

origin  git@github.com:username/repo.git (fetch)
origin  git@github.com:username/repo.git (push)
gitlab  git@gitlab.com:username/repo.git (fetch)
gitlab  git@gitlab.com:username/repo.git (push)

这样你就同时关联了两个远程。

3. 同时推送到两个远程仓库

有两种方式:

方式一:手动分别推送

git push origin main
git push gitlab main

灵活且安全,但要多执行一次命令。

方式二:配置多推送地址,实现一次命令推送两个远程

编辑 .git/config,在 [remote "origin"] 下添加多条 pushurl:

[remote "origin"]
    url = git@github.com:username/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
    pushurl = git@github.com:username/repo.git
    pushurl = git@gitlab.com:username/repo.git

此后执行:

git push origin main

就会同步推送到 GitHub 和 GitLab 两个仓库。

警告

如果用于 CI/CD,请确保两个仓库的流水线不会因同一提交重复触发,这点很重要。

额外操作:重命名或删除远程

重命名远程:

git remote rename origin github1

删除远程:

git remote remove gitlab1

提示

为什么要用两个远程?

  • 备份:GitHub 崩了,GitLab 还在;
  • 迁移:试用新平台,旧平台继续线上运行;
  • 镜像:想多地方展示代码,简单又直观;
  • CI/CD 分离:GitHub 管理代码,GitLab 管理部署。

Submodule

介绍

Git Submodule 允许你在一个 Git 仓库中引用另一个 Git 仓库,作为其子目录(子模块)。这个子目录实际上是一个指向另一个 Git 仓库的指针(哈希值),而不是实际的文件。这样,你就可以在父仓库中维护一个或多个子模块仓库,每个子模块仓库都有自己的版本历史、分支和标签。

项目中经常使用别人维护的模块,在git中使用子模块的功能能够大大提高开发效率。
使用子模块后,不必负责子模块的维护,只需要在必要的时候同步更新子模块即可。使用子模块后,不必负责子模块的维护,只需要在必要的时候同步更新子模块即可。

提示

子模块有自己的分支和标签,与父仓库的分支和标签是分开的。你可以在子模块中切换到不同的分支,进行开发或测试。但是,在父仓库中,你只能通过更新子模块的提交ID来引用子模块的不同版本。

git 将 submodule 有关的信息保存在两个地方:

  • .gitmodules:在仓库中,有版本控制,修改之后会同步到其他仓库,使用 submodule 相关命令的时候会自动更新
  • .git/config:在本地,需要手动更新,或者执行 git submodule sync 将新的配置从 .gitmodules 拷贝到 .git/config
  • .git submodule sync: 会将 submodule 远程的 url 配置设置到 .gitmodules ,并且只会影响 .git/config 已经有 url 的条目,指定 –recursive ,将会递归更新注册的 submodule 。

添加

git submodule add <repository> <path>
# 通过 -b 指定对应分支
git submodule add -b master [URL to Git repo];

其中 <repository> 是子模块仓库的 URL,<path> 是子模块在父仓库中的路径。

注

示例:

# 在 libs 目录下添加一个子模块
git submodule add https://github.com/example/library.git libs/mylibrary

# 初始提交
# 添加子模块后,需要提交 .gitmodules 文件和子模块目录
git add .gitmodules libs/mylibrary
git commit -m "添加子模块: mylibrary"

执行成功后

  • git status 会看到项目中修改了 .gitmodules ,并增加了一个新文件(为刚刚添加的路径)
  • git diff --cached 查看修改内容可以看到增加了子模块,并且新文件下为子模块的提交hash摘要
  • git commit 提交即完成子模块的添加。

clone 含有 submodule 的仓库

完整克隆(推荐)

# 一次性克隆主项目和所有子模块
git clone --recurse-submodules <repository_url>

分步克隆

当 clone 的项目中带有 submodule 时,默认 submodule 的内容并不会自动下载,有两种方法:

  1. # 1. 先克隆主项目
    git clone <repository_url>
    cd <project_name>
    
    # 2. 初始化子模块配置
    git submodule init
    
    # 3. 拉取子模块最新内容
    git submodule update
    
  2. # 一次性初始化并更新所有子模块
    git submodule update --init
    
    # 或
    
    # 递归初始化所有嵌套子模块
    git submodule update --init --recursive
    

执行后,子模块目录下就有了源码,再执行相应的makefile即可。

更新

子模块的维护者提交了更新后,使用子模块的项目必须手动更新才能包含最新的提交。

  1. 主项目中更新所有子模块

    git submodule update --remote
    
  2. 更新单个子模块

    cd libs/mylibrary
    git pull [origin] [main]
    
    # 查看相应提交
    git log
    
    # 返回主目录
    cd ../..
    
    # 添加子模块新增内容
    git add libs/mylibrary
    git commit -m "更新子模块版本"
    

修改分支

如果创建子模块时没有指定分支,可以使用以下命令切换分支

其中 projectName 为主项目名, submoduleA 为子模块名, git checkout 切换到我们的对应分支,然后拉取对应分支代码

cd libs/mylibrary
git checkout master
cd ../..
# 批量操作所有子模块
git submodule foreach git pull
cd ..

指定子模块分支

# 在 .gitmodules 中设置分支
git config -f .gitmodules submodule.libs/mylibrary.branch main

# 更新时使用指定分支
git submodule update --remote --remote

批量操作所有子模块

# 在所有子模块中执行命令
git submodule foreach git pull

# 示例:检查所有子模块状态
git submodule foreach git status

删除子模块

  1. 删除子模块条目

    git submodule deinit -f libs/mylibrary
    
    
  2. 从工作区删除文件

    rm -rf .git/modules/libs/mylibrary
    git rm -f libs/mylibrary
    
  3. 提交更改

    git commit -m "删除子模块 mylibrary"
    

识别项目中的 Submodule

查看子模块信息

# 查看所有子模块状态
git submodule status

# 查看子模块摘要信息
git submodule summary

# 查看 .gitmodules 文件内容
cat .gitmodules

# 或使用 git 命令查看
git config --file .gitmodules --list

识别子模块文件夹

# 子模块文件夹通常显示为特殊模式
ls -la
# 子模块文件夹显示为:@b9b8c6f libs/mylibrary

# 查看 git 跟踪的文件类型
git ls-tree -r HEAD --name-only

子模块更新冲突

# 如果子模块更新出现冲突,可以重置
git submodule update --init --force

# 或进入子模块手动解决冲突
cd libs/mylibrary
# 查看冲突
git status
# 解决冲突后提交
最近更新: 2025/12/18 01:35
Contributors: Enlin
Prev
Linux
Next
Nginx