Git学习文档

Git


安装

无脑下一步


配置

name和email

1
2
git config --global user.name "earstrive"
git config --global user.email "1491157227@qq.com"

使用git

  • 查看当前仓库状态

    1
    git status
  • 初始化仓库

    1
    git init
  • 文件状态

    1. 未跟踪

      • 刚刚添加到项目中的文件处于未跟踪状态
    2. 已跟踪

    3. 暂存

    4. 未修改

    5. 已修改

  • 未跟踪 —> 暂存

    1
    2
    git add <filename>  # 将文件切换到暂存状态
    git add * # 将所有已修改(未跟踪)的文件暂存
  • 暂存 —> 未修改

    1
    2
    git commit -m "xxxx"  # 将暂存的文件存储到仓库中
    git commit -a -m "xxxx" # 提交所有已修改文件(未跟踪的文件不会提交)
  • 未修改 —> 修改

    修改代码后,文件会变为修改状态

  • 查看记录

    1
    git log

Git提交的常用规范

  1. feat: 新功能(feature)
    • 用于提交新功能。
    • 例如:feat: 增加用户注册功能
  2. fix: 修复 bug
    • 用于提交 bug 修复。
    • 例如:fix: 修复登录页面崩溃的问题
  3. docs: 文档变更
    • 用于提交仅文档相关的修改。
    • 例如:docs: 更新README文件
  4. style: 代码风格变动(不影响代码逻辑)
    • 用于提交仅格式化、标点符号、空白等不影响代码运行的变更。
    • 例如:style: 删除多余的空行
  5. refactor: 代码重构(既不是新增功能也不是修复bug的代码更改)
    • 用于提交代码重构。
    • 例如:refactor: 重构用户验证逻辑
  6. perf: 性能优化
    • 用于提交提升性能的代码修改。
    • 例如:perf: 优化图片加载速度
  7. test: 添加或修改测试
    • 用于提交测试相关的内容。
    • 例如:test: 增加用户模块的单元测试
  8. chore: 杂项(构建过程或辅助工具的变动)
    • 用于提交构建过程、辅助工具等相关的内容修改。
    • 例如:chore: 更新依赖库
  9. build: 构建系统或外部依赖项的变更
    • 用于提交影响构建系统的更改。
    • 例如:build: 升级webpack到版本5
  10. ci: 持续集成配置的变更
    • 用于提交CI配置文件和脚本的修改。
    • 例如:ci: 修改GitHub Actions配置文件
  11. revert: 回滚
    • 用于提交回滚之前的提交。
    • 例如:revert: 回滚feat: 增加用户注册功能

常用的命令

  • 重置文件

    1
    2
    git restore <filename>  # 恢复文件
    git restore --staged <filename> # 取消暂存状态

  • 删除文件

    1
    2
    git restore <filename>  # 恢复文件
    git restore --staged <filename> # 取消暂存状态

  • 移动文件

    1
    git mv from to  # 移动文件 重命名文件

分支

git在存储文件时,每一次代码的提交都会创建一个与之对应的节点,git就是通过一个一个的节点来记录代码的状态的。节点会构成一个树状结构,树状结构就意味着会存在分支,默认情况下仓库只有一个分支,命名为master。在使用git时,可以创建多个分支,分支与分支之间相互独立,在一个分支上修改代码不会影响其他分支。

1
2
3
4
5
6
7
git branch  # 查看当前分支
git branch <branch name> # 创建新的分支
git branch -d <branch name> # 删除分支
git switch <branch name> # 切换分支
git switch -c <branch name> # 创建并切换分支
git merge <branch name> # 合并分支
git checkout -b <new-branch> # 创建并切换到新分支

在开发中,都是在自己的分支上编写代码,代码编写完成后,在将自己的分支合并到主分支中


变基(rebase)

在开发中除了通过merge合并分支外,还可以通过变基来完成分支的合并

我们通过merge合并分支时,在提交记录中会将所有的分支创建和分支合并的过程全部都显示出来,这样当项目比较复杂,开发过程比较波折时,我必须要反复的创建、合并、删除分支。这样一来将会使得我们代码的提交记录变得极为混乱。

原理(变基时发生了什么):

  1. 当我们发起变基时,git会首先找到两条分支的共同祖先
  2. 对比当前分支相对于祖先的历史提交,并且将它们提取出来存储到临时文件中
  3. 将当前部分指向目标的基底
  4. 以当前基底开始,重新执行历史操作

变基和merge对合并分支来说最终的结果是一样的,但是变基会使得代码的提交记录更整洁更清晰,注意:大部分情况下合并和变基是可以互换的,但是如果分支已经提交给了远程仓库,那么这时尽量不要变基。


rebase和merge如何选择

git merge 使用与场景

  • 基础命令
1
2
3
4
5
# 切换到目标分支(如 main)
git checkout main

# 合并特性分支
git merge feature
  • 典型场景

    • 公共分支集成(如 main/dev

    • ✅ 保留完整开发历史(包括分支上下文)

    • ✅ 多人协作时合并他人分支

  • 结果示例

1
2
3
4
5
6
*   1a2b3c4 (HEAD -> main) Merge branch 'feature'
|\
| * d5e6f7a (feature) Add new API
| * a8b9c0d Update config
|/
* 00ab11e Initial commit

git rebase 使用与场景

  • 基础命令
1
2
3
4
5
6
7
8
9
# 切换到特性分支
git checkout feature

# 将 feature 变基到 main
git rebase main

# 变基后快速合并(无分叉)
git checkout main
git merge feature
  • 典型场景

    • 本地分支更新(私有分支整理)

    • ✅ 创建更清晰的历史记录(适合开源项目)

    • ✅ 解决因长期开发导致的分支偏离

  • 结果示例(变基后)

1
2
3
4
* d5e6f7a (HEAD -> feature) Add new API
* a8b9c0d Update config
* 1a2b3c4 (main) Fix login bug
* 00ab11e Initial commit

关键注意事项

  • ⚠️ Rebase 黄金法则
    • 不要再主分支上使用rebase
    • 永远不要对已推送到远程仓库的公共分支执行 rebase!

远程仓库(remote)

目前我们对于git所有操作都是在本地进行的。在开发中显然不能这样的,这时我们就需要一个远程的git仓库。远程的git仓库的本质没有什么区别,不同点在于远程的仓库可以被多人同时访问使用,方便我们协同开发。在实际工作中,git的服务器通常由公司搭建内部使用或是购买一些公共的私有git服务器。我们学习阶段,直接使用一些开放的公共git仓库。目前我们常用的库有两个:Github和Gitee(码云)

将本地库上传git:

1
2
3
4
5
6
7
8
git remote add origin https://github.com/earstrive/git-demo.git
# git remote add <remote name> <url>

git branch -M main
# 修改分支的名字为main

git push -u origin main
# git push 将代码上传服务器上

将本地库上传gitee:

1
2
git remote add gitee https://gitee.com/ear-strive/git-demo.git
git push -u gitee main

远程库的操作的命令

本地仓库需要跟踪上游分支后,才能fetch代码,本地分支跟踪(Tracking)上游分支(Upstream Branch)

1
2
3
4
5
6
7
8
9
git remote  # 列出当前的关联的远程库
git remote add <远程库名> <url> # 关联远程仓库
git remote remove <远程库名> # 删除远程库
git push -u <远程库名> <分支名> # 向远程库推送代码,并和当前分支关联
git push <远程库> <本地分支>:<远程分支>
git clone <url> # 从远程库下载代码
git push # 如果本地的版本低于远程库,push默认是腿不上去,推送到关联的分支
git fetch # 要想推送成功,必须先确保本地库和远程库的版本一致,fetch它会从远程仓库下载所有代码,但是他不会将代码和当前分支自动合并 使用fetch拉取代码后,必须要手动对代码进行合并(merge) git merge origin/master
git pull # 从服务器上拉取代码并自动合并 相当于 git fetch + git merge

注意:推送代码之前,一定要先重远程库中拉去最新的代码


tag标签

  • 当头指针没有指向某个分离的头部时,这种状态我们称为分离头指针,分离头指针状态下也可以操作代码,但是这些操作不会出现在任何的分支上,所以注意不要再分离头指针的状态下来操作仓库。


  • 如果非得要回到后边的节点对代码进行操作,则可以选择创建分支后再操作

    1
    git switch -c <分支名> <提交id>  # git switch -c test aab508

  • 可以为提交记录设置标签,设置标签后,可以通过标签快速的识别出不同的开发节点:

    1
    2
    3
    4
    5
    6
    7
    git tag 版本  # git tag v1.0
    git tag 版本 提交id # git tag v0.5 aab508
    git push 远程仓库 标签名 # git push origin v1.0
    git push 远程仓库 --tags # 推送所有标签
    git tag -d 标签名 # 删除本地标签
    git push 远程仓库 --delete 标签名 # 删除远程标签
    git checkout v1.0 # 检出tag 通常我们在检出tag的时候还会创建一个对应的分支

gitignore

  • 默认情况下,git会监视项目中所有内容,但是有些内容比如node_modules目录中的内容,我们不希望它被git所管理。我们可以在项目目录中添加一个.gitignore 文件,来设置那些需要git忽略的文件

    1
    2
    3
    # 注释
    node_modules
    yarn.lock

工作流

  1. 初始化仓库:git init

  2. 连接远程仓库

    • Github:

      1
      2
      3
      4
      5
      6
      7
      8
      git remote add origin https://github.com/earstrive/git-demo.git
      # git remote add <remote name> <url>

      git branch -M main
      # 修改分支的名字为main

      git push -u origin main
      # git push 将代码上传服务器上
    • Gitee

      1
      2
      git remote add gitee https://gitee.com/ear-strive/git-demo.git
      git push -u gitee main
  3. 初始化项目完成提交后创建开发分支:git branch dev

  4. 分支管理:

    • masterz作为主分支
    • dev作为开发分支,并且有稳定版本时,合并到master分支中
    • topic作为某一个主题或者功能或者特性的分支进行开发,开发完成后合并到dev分支中
  5. 项目在开发分支完成大版本并且可用后合并到主上:

    • 使用合并:git switch master git merge dev
    • 使用变基:git checkout dev git rebase main git checkout main git merge feature
  6. 切换到主分支为开发完成后的项目添加版本标签:git tag 版本

  7. 主分支上向远程仓库推送代码:git push -u origin main git push -u gitee main git push 远程仓库 --tags


一些DeepSeek回答的问题

1.git push -u origin main 中这个 -u 是做了什么操作

git push -u origin main 命令中,-u 参数的作用是设置上游分支(Upstream Branch),即建立本地分支与远程分支的追踪关系。以下是具体操作和底层原理的解析:


1. 核心功能

  • 关联本地与远程分支
    -u--set-upstream 的缩写,它会将本地当前分支(如 main)与指定的远程分支(如 origin/main)绑定。绑定后,Git 会记录这种关联关系,后续的 git pushgit pull 命令无需再显式指定远程仓库和分支名。
  • 简化后续操作
    设置上游分支后,后续可直接使用 git push(无需 origin main)或 git pull,Git 会自动根据关联关系推送到或拉取远程分支。

2. 底层实现

  • 修改 Git 配置文件
    执行 -u 参数后,Git 会在本地仓库的 .git/config 文件中添加如下配置:

    1
    2
    3
    [branch "main"]
    remote = origin
    merge = refs/heads/main

    这表示本地 main 分支的默认远程仓库是 origin,且追踪的远程分支是 origin/main

  • 追踪分支的用途
    该配置让 Git 在以下场景自动识别目标分支:

    • git push:默认推送到 origin/main
    • git pull:默认从 origin/main 拉取并合并代码。

3. 适用场景

  • 首次推送本地分支
    当本地分支首次推送到远程仓库时,-u 参数会同时完成推送和关联操作。例如,新项目初始化或创建新分支后首次推送。
  • 团队协作
    多人开发时,通过设置上游分支确保本地分支与远程分支同步,避免手动指定分支名的繁琐操作。
  • 简化日常命令
    后续只需输入 git pushgit pull,减少重复输入参数的错误风险。

4. 注意事项

  • 仅需一次设置
    -u 只需在首次推送时使用,后续操作无需重复添加。

手动修改关联关系

若需更改追踪的远程分支,可通过以下命令重置:

1
git branch --set-upstream-to=origin/<新分支名>

总结

-u 参数的核心是建立本地与远程分支的“绑定”关系,通过修改配置文件实现后续命令的自动化。这一操作在首次推送、团队协作和简化日常流程中尤为重要。


2.但是git config push.default 默认不是simple吗,假如远程分支名和本地不一样,那是不是后续的push会推送不上去

您提出了一个非常关键的点!确实,当 git config push.default 设置为 simple(Git 2.0+ 的默认值)时,如果本地分支名和远程分支名不一致,后续直接运行 git push 会失败。这是 Git 的安全机制设计。以下是详细解释和解决方案:


🔍 问题核心:push.default = simple 的行为

  1. simple 模式规则

    • 仅当本地分支名 严格匹配 其跟踪的远程分支名时,才允许直接使用 git push
    • 如果名称不匹配,Git 会拒绝推送并提示错误
  2. 错误示例

    1
    2
    3
    4
    5
    # 假设推送时指定了不同名称
    git push -u origin local-branch:remote-branch

    # 后续尝试直接推送
    git push

    报错信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    fatal: The upstream branch of your current branch does not match
    the name of your current branch. To push to the upstream branch
    on the remote, use:

    git push origin HEAD:remote-branch

    To push to the branch of the same name on the remote, use:

    git push origin local-branch

✅ 解决方案(3种方法)

方法1:保持分支名一致(推荐)
1
2
3
4
5
# 首次推送时确保本地与远程同名
git push -u origin local-branch # 远程自动创建 local-branch

# 后续可直接使用
git push
方法2:显式指定推送目标(绕过限制)
1
2
# 每次推送都完整指定
git push origin local-branch:remote-branch
方法3:修改 Git 配置(不推荐)
1
2
3
4
5
# 改为 upstream 模式(允许不同名)
git config push.default upstream

# 后续推送行为:
# git push 会推送到跟踪的远程分支(无论是否同名)

⚠️ 注意upstream 模式可能导致意外推送,Git 官方文档建议优先使用 simple


🌰 实际场景演示

情况1:同名分支(正常工作)
1
2
3
4
5
# 本地分支:feature
git push -u origin feature # 推送到 origin/feature

# 后续推送
git push # 成功 → 推送到 origin/feature
情况2:不同名分支(会报错)
1
2
3
4
5
# 本地分支:dev
git push -u origin dev:stable # 推送到 origin/stable

# 后续推送
git push

报错

1
2
3
fatal: The current branch dev has no upstream branch.
To push the current branch and set the remote as upstream, use:
git push --set-upstream origin dev:stable

📌 最佳实践总结

场景 推荐操作
新功能开发 git push -u origin 同名分支
需要推送到不同名的远程分支 始终使用完整命令:git push origin 本地:远程
团队协作主干分支 保持本地分支与远程同名

💡 设计理念simple 模式强制开发者显式处理名称差异,避免意外覆盖重要分支(如 maindevelop 的误操作)

通过保持本地分支名与远程分支名一致,可以充分利用 Git 的简化工作流,同时符合安全规范。