> 技术文档 > git 常用命令_git常用命令

git 常用命令_git常用命令


文章目录

  • config
    • 1. 临时修改用户名和邮箱
    • 2. 全局修改用户名和邮箱
  • remote
    • 1. 查看当前远程地址
    • 2. 修改远程地址
    • 3. 验证修改
    • 4. 推送到新地址
    • 5. 添加或替换其他远程地址
    • 6. 删除远程地址
    • 总结
  • clone
  • .gitignore
    • 语法规则
      • 忽略指定文件或目录
      • 忽略某种类型的文件
      • 使用 ! 例外规则
      • 使用 / 指定目录
      • 使用 ** 进行递归匹配
    • 生效规则
      • 已经被 Git 跟踪的文件不会被忽略
      • 如何检查某个文件是否被忽略
    • 总结
  • commit
    • 修改最近一次提交中的文件(未 push)
    • 修改更早之前的某个提交(未 push)
    • 修改已经 push 到远程的提交
  • reset
    • 1. 丢弃已暂存的修改
    • 2. 丢弃工作区的修改
    • 3. 一步完成(同时丢弃暂存区和工作区的修改)
    • 4. 取消最近的 commit(保留文件变更)
    • 5. 取消最近的 commit(不保留文件变更)
    • 6. 取消指定的 commit(回退到某个历史提交)
    • 7. 撤销已推送到远程的 commit(强制推送)
    • 8. 撤销已提交但未推送的 commit(更改提交信息)
    • 总结
  • revert
    • 使用`git revert`与`git reset`的比较
  • clean
    • 1. 删除所有未追踪文件
    • 2. 删除未追踪的目录
    • 3. 删除未追踪的文件和忽略文件
    • 4. 仅查看即将删除的文件(安全检查)
    • 5. 仅删除某个文件或目录
    • 总结
  • branch
    • 1. 查看分支
    • 2. 创建分支
    • 3. 重命名分支
    • 4. 切换分支
    • 5. 删除分支
    • 6. 合并分支
    • 7. 推送分支
    • 8. 重命名分支
    • 9. 分支比较
    • 10. 分支管理常见流程
    • 总结
  • merge
    • 1. 基本概念
    • 2. 合并的基本步骤
    • 3. 合并模式
      • 3.1 快进合并 (Fast-Forward Merge)
      • 3.2 三方合并 (3-Way Merge)
    • 4. 常用选项
      • 4.1 --squash
      • 4.2 --abort
    • 5. 冲突处理
    • 6. 示例:从开发分支合并到主分支
  • rebase
    • 1. git rebase 的基本用法
      • 基础 rebase
      • 拉取远程代码时使用 rebase
    • 2. 交互式 rebase(git rebase -i)
      • 合并提交(squash & fixup)
      • 修改某个提交(edit)
      • 删除某个提交
    • 3. rebase 解决冲突
    • 4. git rebase 高级用法
      • 变基远程分支
      • 将分支变基到另一分支
      • 合并多个分支提交
    • 5. rebase 发生问题时的撤销
    • 总结
  • cherry-pick
    • 1. 用法
    • 2. 提交多个hash
      • 2.1 挑选一组不连续的提交
      • 2.2 暂停的 Cherry-Pick
    • 3. cherry-pick 选项
      • 3.1 -e / --edit
      • 3.2 -n / --no-commit
      • 3.3 -x
  • rm
    • 1. 常用操作
      • 1.1 删除文件并将其从暂存区移除
      • 1.2 只从暂存区移除文件,保留本地文件
    • 2. 选项详解
      • 2.1 `--cached`
      • 2.2 `-f` 或 `--force`
      • 2.3 `-r`
    • 3. 注意事项
      • 3.1 删除的文件如何恢复?
      • 3.2 `.gitignore` 的配合使用
    • 总结
  • tag
    • 1. 查看现有标签
    • 2. 创建附注标签
    • 3. 给特定的提交打标签
    • 4. 推送标签到远程仓库
    • 5. 删除标签
    • 6. 检查标签详细信息
    • 7. 拉取标签
    • 8. 拉取标签和代码的区别
    • 9. 检出到某个标签
  • stash
    • `git stash`
    • `git stash list`
    • `git stash show`
    • `git stash apply`
    • `git stash pop`
    • `git stash drop stash@{n}`
    • `git stash clear`
  • log
    • 常用命令
      • 查看特定文件的提交记录
      • 查看某个分支的提交记录
      • 显示提交历史的分支结构
    • 统计提交次数
    • 仅查看文件变更
    • 格式化日志
    • 结合 grep 搜索提交
    • 全面查看提交历史
    • 查看提交内容
    • 总结
  • show和diff 区别
    • git show
    • git diff
    • 区别总结
  • submodule
    • 什么是子仓库?
    • 常用操作
      • 1.添加子仓库
      • 2. 初始化子仓库
      • 3. 更新子仓库
      • 4. 删除子仓库
    • .gitmodules 文件详解
    • 常见问题
      • 子仓库未初始化如何解决?
      • 取消子仓库在主仓库中的未追踪中展示
  • 问题记录
    • Gitee exceeds quota 100MB

config

1. 临时修改用户名和邮箱

如果只需要修改当前仓库的提交者信息,可以使用以下命令:

git config user.name \"新用户名\"git config user.email \"新邮箱地址\"

查看配置:

git config user.namegit config user.email

注意:此修改仅对当前仓库有效,不会影响全局配置或其他仓库。

2. 全局修改用户名和邮箱

如果希望更改所有仓库的默认用户名和邮箱,可以使用全局配置:

git config --global user.name \"新用户名\"git config --global user.email \"新邮箱地址\"

查看全局配置:

git config --global user.namegit config --global user.email

remote

1. 查看当前远程地址

git remote -v

输出示例:

origin https://github.com/user/old-repo.git (fetch)origin https://github.com/user/old-repo.git (push)

2. 修改远程地址

修改 origin 的 URL

git remote set-url origin <new-remote-url>

示例:

git remote set-url origin https://github.com/user/new-repo.git

3. 验证修改

再次查看远程地址,确保已经更改成功:

git remote -v

输出示例:

origin https://github.com/user/new-repo.git (fetch)origin https://github.com/user/new-repo.git (push)

4. 推送到新地址

验证后,你可以尝试推送代码到新的远程仓库:

git push origin main

5. 添加或替换其他远程地址

添加新的远程地址:
如果需要保留旧的远程地址并添加新的远程仓库,可以使用以下命令:

git remote add <name> <new-remote-url>

示例:

git remote add upstream https://github.com/user/another-repo.git

查看多个远程:

git remote -v

输出示例:

origin https://github.com/user/new-repo.git (fetch)origin https://github.com/user/new-repo.git (push)upstream https://github.com/user/another-repo.git (fetch)upstream https://github.com/user/another-repo.git (push)

6. 删除远程地址

git remote remove <name>

总结

操作 命令 查看远程地址 git remote -v 修改远程地址 git remote set-url origin 添加远程地址 git remote add 删除远程地址 git remote remove

clone

克隆仓库
首先,使用 git clone 命令克隆整个仓库到你的本地机器。如果你只想克隆特定的分支,而不是克隆整个仓库的所有分支和历史记录,可以使用 --branch-b 选项指定分支名。

git clone -b <branch-name> <repository-url># 例如,如果你想克隆一个名为 feature-x 的分支:git clone -b feature-x https://github.com/user/repo.git

.gitignore

语法规则

.gitignore 文件的每一行都表示一个忽略规则。以下是 .gitignore 规则的基本语法

忽略指定文件或目录

  • 忽略某个文件
    myfile.txt

    忽略 myfile.txt 文件

  • 忽略某个目录(及其所有内容)
    mydir/

    忽略 mydir 目录及其所有子文件。

忽略某种类型的文件

  • 忽略所有 .log 结尾的日志文件:
    *.log

    忽略所有 .log 文件,如 error.logdebug.log

使用 ! 例外规则

可以使用 ! 号来排除某些文件,即即使符合上面的规则,也不要忽略这些文件

  • 忽略 logs 目录下的所有 .log 文件,但 important.log 除外
    logs/*.log!logs/important.log

    这个规则的意思是:忽略 logs 目录下的 .log 文件,但 important.log 例外,不会被忽略。

使用 / 指定目录

  • / 表示相对 .gitignore 文件所在目录的路径
    /node_modules/

    这只会忽略仓库根目录下的 node_modules/ 目录,而不会影响子目录下的 node_modules/

  • 不使用 /,则匹配所有层级的 node_modules/
    node_modules/

    这会忽略所有 node_modules/ 目录,包括子目录下的 node_modules/

使用 ** 进行递归匹配

  • ** 表示匹配任意目录

    **/temp/

    这会忽略所有 temp/ 目录,不管它位于哪个层级。

  • 忽略所有 .log 文件,不论在哪个子目录:

    **/*.log

    这会忽略整个项目中所有 .log 文件。

生效规则

已经被 Git 跟踪的文件不会被忽略

如果一个文件已经被 Git 跟踪,即使 .gitignore 规则匹配它,也不会被忽略。

解决方案: 如果你想让 .gitignore 规则对已经被 Git 跟踪的文件生效,你需要先将它从 Git 追踪中移除:

git rm -r --cached <file_or_directory># 例如git rm -r --cached node_modules/# 然后提交更改:git commit -m \"更新 .gitignore 规则\"git push origin main

如何检查某个文件是否被忽略

你可以使用 git check-ignore 命令来检查某个文件是否会被 .gitignore 忽略

git check-ignore -v <file># 例如 如果 debug.log 在 .gitignore 规则中,它会返回匹配的规则git check-ignore -v logs/debug.log

总结

  • .gitignore 用于忽略不需要提交的文件,避免污染 Git 仓库。
  • 规则包括:忽略单个文件、目录、文件类型、特定层级目录等。
  • 可以使用 ! 例外规则来指定不被忽略的文件。
  • 规则一旦生效,必须先用 git rm --cached 移除已被 Git 追踪的文件,否则 .gitignore 不会生效。
  • 使用 git check-ignore -v 进行调试,确认文件是否被忽略。

掌握 .gitignore 规则可以帮助你更高效地管理 Git 仓库,提高团队协作的效率。

commit

修改最近一次提交中的文件(未 push)

如果你刚提交,发现文件有错,想修改并更新到上一次提交:

# 修改文件,编辑保存vim your_file.txt# 添加修改git add your_file.txt# 修改最近一次提交,合并新的更改git commit --amend
  • git commit --amend 会把你的修改追加到上一次提交里,修改提交信息时会打开编辑器,你也可以用 -m \"new message\" 直接写提交信息。

修改更早之前的某个提交(未 push)

如果你想修改历史上某个提交:

git rebase -i <commit_id>^
  • 会进入交互式界面,找到你想修改的提交,把 pick 改成 edit
  • 保存退出后,Git 会停在那个提交,你可以修改文件:
    vim your_file.txtgit add your_file.txtgit commit --amend
  • 然后继续 rebase
    git rebase --continue

修改已经 push 到远程的提交

如果修改的提交已经推送到远程仓库(尤其是公共分支),需要谨慎操作,因为这会重写历史,可能导致别人拉取代码冲突。

  • 操作同上,完成修改后强制推送:
    git push --force

    ⚠️ 注意:请确保所有协作者都知道这一操作!

reset

在 Git 中,如果你已经执行了 git add,将文件的更改暂存到索引区,但又想丢弃这些修改,可以通过以下步骤实现

1. 丢弃已暂存的修改

git reset HEAD <file>

或者丢弃所有已暂存的文件

git reset HEAD

作用:

  • git reset HEAD 会将指定文件从暂存区移回工作区,修改仍然保留在工作区中,但不会再被标记为已暂存。
    示例:
    git reset HEAD myfile.txt

    此命令将 myfile.txt 的修改移出暂存区

2. 丢弃工作区的修改

在执行完 git reset HEAD 后,如果还想丢弃工作区的更改,可以使用以下命令

git checkout -- <file>

或者丢弃所有文件的更改

git checkout -- .

作用:

  • git checkout -- 会将文件恢复到上一次提交时的状态,丢弃工作区中的修改

3. 一步完成(同时丢弃暂存区和工作区的修改)

如果想直接同时丢弃暂存区和工作区的所有修改,可以使用以下命令

git reset --hard HEAD

作用:

  • 此命令将工作区和暂存区重置到最后一次提交的状态,所有未提交的更改都会被丢弃。
  • ⚠️ 注意:此命令会直接丢弃所有未提交的修改,不可恢复,操作前请确认没有重要内容。

4. 取消最近的 commit(保留文件变更)

这个命令会取消最新的提交,但保留修改,使其回到暂存区。

如果你只想取消最近的 commit,但是保留这些文件的修改(即将这些修改放回暂存区)

git reset --soft HEAD~1
  • --soft:将 HEAD 指针回退到前一个提交(即 HEAD~1),但是保留工作区和暂存区的变更,变 更会被放回到暂存区。
  • HEAD~1:表示上一个提交。

5. 取消最近的 commit(不保留文件变更)

这会完全删除最近的提交,包括你在工作区和暂存区的所有变更,因此要小心使用。

如果你希望取消最近的 commit,并且不保留任何修改(即删除这些更改)

git reset --hard HEAD~1
  • --hard:将 HEAD 回退到前一个提交,并丢弃工作区和暂存区的所有更改。

6. 取消指定的 commit(回退到某个历史提交)

这个命令会将 HEAD 指针和分支指针回退到指定的提交,并且丢弃回退后所有的提交。

如果你想取消某个历史提交,而不是仅仅取消最新的 commit

git reset --hard <commit_id>
  • :是你希望回退到的目标提交的哈希值(例如 a1b2c3d4)。

7. 撤销已推送到远程的 commit(强制推送)

警告:强制推送会修改远程仓库的历史,可能会影响其他协作开发者的代码,因此必须谨慎操作,最好在团队中协调好后再执行。

如果你已经将 commit 推送到远程仓库,并且想撤销这些提交,需要谨慎操作。假设你已经执行了某些 commit,并推送到远程仓库。你可以通过以下步骤取消这些提交并强制推送。

# 首先,使用 git reset 取消本地的提交:git reset --hard HEAD~1# 然后,使用 git push 强制推送到远程仓库:git push origin <branch_name> --force

8. 撤销已提交但未推送的 commit(更改提交信息)

这将允许你修改最新提交的提交信息,而不需要重新提交更改。修改完提交信息后,保存并退出编辑器,新的提交信息将会生效。

如果你仅想修改提交信息,而不想撤销整个提交,可以使用 git commit --amend 来修改最近的提交:

git commit --amend

总结

场景 操作 仅取消暂存区的修改 git reset HEAD 取消暂存区修改并恢复文件内容 git reset HEAD → git checkout -- 直接丢弃所有已暂存和未暂存的修改 git reset --hard HEAD 撤销最近的提交并保留更改在暂存区 git reset --soft HEAD~1 撤销最近的提交并丢弃更改 git reset --hard HEAD~1 撤销最近的提交并保留更改在工作区 git reset --mixed HEAD~1 回退到某个指定的提交,丢弃所有之后的提交 git reset --hard 修改最近一次提交的信息 git commit --amend

revert

git revert命令用于创建一个新的commit,该commit会撤销指定commit的更改。这种方法不会改变历史,而是在历史中添加一个新的commit来抵消之前的更改。

例如,要回滚到HEAD~3(即当前commit的前三个commit),可以执行以下命令:

git revert HEAD~3

这会打开默认的文本编辑器,要求你输入提交信息。输入完毕后保存并退出,Git将创建一个新的commit,撤销HEAD~3的更改。

使用git revertgit reset的比较

git revert:创建一个新的commit来撤销之前的更改,不改变历史。适用于公共仓库,因为它不会破坏其他人的工作。
git reset:移动HEAD指针到指定commit,可以选择性地更改索引和工作目录。可能会改变历史,因此不适用于公共仓库。

clean

Git 中,丢弃未追踪(未纳入版本控制)的文件,即 删除本地未添加到 Git 的文件,可以使用以下命令

1. 删除所有未追踪文件

git clean -f
  • -f--force):强制删除未追踪的文件(未 git add 的文件)。

  • ⚠️ 注意:此操作不可撤销,执行前请确保不误删重要文件!

2. 删除未追踪的目录

如果未追踪的文件在目录下,并且要删除整个目录:

git clean -fd
  • -d:删除未追踪的目录。

3. 删除未追踪的文件和忽略文件

如果你希望连 .gitignore 里被忽略的文件也一并删除:

git clean -xfd
  • -x:删除 所有未追踪的文件,包括 .gitignore 里忽略的文件。

4. 仅查看即将删除的文件(安全检查)

在执行删除前,建议先用 -n 选项进行检查

git clean -n

示例输出:

Would remove temp.txtWould remove logs/debug.log

确认后再执行 git clean -f 进行删除!

5. 仅删除某个文件或目录

如果你只想删除特定的未追踪文件或目录,例如 temp.txt

git clean -f temp.txt

或者删除 logs/ 目录:

git clean -fd logs/

总结

命令 作用 git clean -n 查看即将删除的文件(安全检查)。 git clean -f 删除 所有未追踪文件。 git clean -fd 删除 未追踪的文件 + 目录。 git clean -xfd 删除所有未追踪文件 + 目录 + .gitignore里的文件。 git clean -f 删除特定未追踪文件或目录。

🚀 建议先执行 git clean -n 确认文件后,再执行 git clean -f 避免误删!

branch

在 Git 中,分支操作是项目开发中非常常见的任务。以下是关于分支操作的常用命令及详细说明。

1. 查看分支

# 查看本地分支git branch# 查看远程分支git branch -r# 查看本地和远程分支git branch -a

2. 创建分支

# 创建分支git branch <branch_name># 创建新分支并且切换到该分支git checkout -b <branch_name>

3. 重命名分支

git branch -m 旧分支 新分支

4. 切换分支

# 切换到指定分支git checkout <branch_name># 指定提交切换分支git checkout <branch_name> <commit_hash>

5. 删除分支

# 删除本地分支(只适用于已合并的分支)git branch -d <branch_name># 强制删除本地分支 (未合并的也会被删除)git branch -D <branch_name># 删除远程分支git push origin --delete <branch_name>

6. 合并分支

# 将指定分支合并到当前分支git merge <branch_name>

合并冲突处理:

  1. Git 会提示冲突文件。
  2. 编辑冲突文件,解决冲突。
  3. 将修改后的文件标记为解决:
    git add <file>
  4. 完成合并
    git commit -m <desc>

7. 推送分支

git push origin <branch_name>

8. 重命名分支

# 重命名当前分支git branch -m <new_branch_name># 重命名指定分支git branch -m <old_branch_name> <new_branch_name>

9. 分支比较

git diff <branch_1> <branch_2>

10. 分支管理常见流程

开发新功能

  1. 创建新分支:
    git switch -c feature/new-feature
  2. 开发并提交代码:
    git add .git commit -m \"Add new feature\"
  3. 推送新分支到远程:
    git push origin feature/new-feature

合并分支到主分支

  1. 切换到主分支:
    git switch main
  2. 拉取最新代码:
    git pull origin main
  3. 合并功能分支:
    git merge feature/new-feature
  4. 删除功能分支(可选):
    git branch -d feature/new-featuregit push origin --delete feature/new-feature

总结

操作 命令 查看分支 git branch 创建分支 git branch 切换分支 git switch 删除分支 git branch -d 合并分支 git merge 推送分支 git push origin 跟踪分支 git branch --set-upstream-to=origin/

merge

git merge 是 Git 中用于将多个分支的内容合并到一个分支的操作。它是团队协作开发中处理分支合并的核心命令之一。

1. 基本概念

  • git merge 的作用:将另一个分支的更改整合到当前分支。
  • 合并的前提:必须在某个分支上运行 git merge 命令,目标是将另一个分支的更改合并到当前分支。

2. 合并的基本步骤

  1. 切换到目标分支(合并到哪个分支):
    git checkout <target-branch># 或者更常用的方式:git switch <target-branch>
  2. 执行合并:
    # 将 source-branch 的更改合并到 target-branch。git merge <source-branch>
  3. 解决冲突(如有):
    • 如果合并过程中有冲突,Git 会提示哪些文件有冲突。
    • 手动编辑冲突的文件,解决冲突后执行:
    git add <conflicted-file>git commit

3. 合并模式

git merge 主要有两种模式:快进合并(Fast-Forward) 和 三方合并(3-Way Merge)。

3.1 快进合并 (Fast-Forward Merge)

  • 条件:如果当前分支的 HEAD 是目标分支的祖先(没有分叉历史)。
  • 结果:直接将 HEAD 移动到目标分支的最新提交,历史记录呈直线。

示例:

# 假设分支状态如下:# main: A -> B# feature: A -> B -> Cgit switch maingit merge feature# 合并后:# main: A -> B -> C

特点:

  • 不会生成额外的合并提交。
  • 合并历史简单清晰,但不适合需要保留分支开发历史的情况。

3.2 三方合并 (3-Way Merge)

  • 条件:如果当前分支和目标分支都有各自的提交记录(有分叉历史)。
  • 结果:创建一个新的合并提交,记录两个分支的历史。

示例:

# 假设分支状态如下:# main: A -> B# feature: A -> Cgit switch maingit merge feature# 合并后:# main: A -> B -> D (merge commit)#  ↘ C

特点:

  • 生成一个合并提交,记录了两个分支的提交历史。
  • 更适合复杂的分支开发场景。

4. 常用选项

git merge 支持多种选项来满足不同场景的需求:

4.1 --squash

  • 将另一个分支的所有提交压缩为一个提交,然后合并到当前分支。
  • 常用于临时分支开发,将多个提交压缩成一个干净的提交。

示例:

git merge --squash featuregit commit -m \"Merge feature branch\"

结果: 不会保留 feature 分支的提交历史,只会将更改作为一个新提交合并。

4.2 --abort

  • 如果在合并过程中遇到冲突且不想继续合并,可以使用此选项终止合并并恢复到合并前的状态。

示例:

git merge feature# 如果冲突了,不想继续:git merge --abort

5. 冲突处理

在合并过程中,如果文件在两个分支中都有修改,可能会发生冲突。
冲突解决步骤:

  1. 查看冲突文件:
    git status
  2. 编辑冲突文件: 手动修改文件,确保内容符合需求。冲突部分通常标记为:
    <<<<<<< HEAD# 当前分支的更改=======# 合并分支的更改>>>>>>> feature
  3. 标记冲突已解决: 修改后添加到暂存区:
    git add <file>
  4. 提交合并结果:
    git commit

6. 示例:从开发分支合并到主分支

# 创建开发分支git checkout -b dev# 在开发分支进行提交echo \"Some changes\" > file.txtgit add file.txtgit commit -m \"Make some changes\"# 切回主线分支合并git switch maingit merge dev# 检测历史git log --oneline --graph

rebase

git rebaseGit 中用于变基(rebase)操作的命令,主要用于重写提交历史,以保持提交记录的整洁,并避免不必要的合并提交(merge commit)。在多人协作时,它有助于保持线性历史,使代码变更更清晰。

1. git rebase 的基本用法

基础 rebase

将当前分支的提交移动到 main 分支的最新提交之后

git checkout feature-branch # 切换到开发分支git rebase main # 让 feature-branch 变基到 main 最新提交上

等价于:

  1. git fetch 获取最新的远程 main 分支。

  2. feature-branch 上的提交一个个“摘下来”。

  3. main 最新提交上重新应用这些提交。

示例

假设当前 git log --oneline --graph 结构如下:

A---B---C (main) \\ D---E (feature-branch)

运行:

git checkout feature-branchgit rebase main

变为:

A---B---C---D\'---E\' (feature-branch)

即:这会“重放” D、E 提交到 main 的末尾,提交哈希变了。

拉取远程代码时使用 rebase

git pull --rebase origin main

等价于:

git fetch origingit rebase origin/main
  • 作用:避免 merge commit,保持干净的提交历史。

  • 适用于: 多人协作时更新远程代码,保持提交线性。

2. 交互式 rebase(git rebase -i)

交互式 rebase 允许你修改多个提交,如合并(squash)、编辑(edit)、删除(drop)、重新排序等。

git rebase -i HEAD~3

这表示对最近 3 次提交执行交互式变基,Git 会打开一个交互界面:

pick abc123 First commitpick def456 Second commitpick ghi789 Third commit

你可以修改 pick 为:

命令 作用 pick 保留该提交(默认值)。 reword 修改提交信息(commit message)。 edit 修改该提交的内容。 squash 合并该提交到前一个提交,并保持前一个提交的 commit messagefixup 合并该提交到前一个提交,并丢弃该提交的 commit messagedrop 删除该提交。

合并提交(squash & fixup)

场景:多个提交可以合并为一个

pick abc123 First commitsquash def456 Second commitfixup ghi789 Third commit
  • squash:合并到上一个提交,并允许修改 commit message

  • fixup:合并到上一个提交,并丢弃自己的 commit message

修改某个提交(edit)

如果 C2 提交有错误但 C3 是正确的:

pick abc123 First commitedit def456 Second commitpick ghi789 Third commit

然后

git commit --amend # 修改 C2 的内容git rebase --continue # 继续 rebase

删除某个提交

pick abc123 First commitdrop def456 Second commit # 删除该提交pick ghi789 Third commit

3. rebase 解决冲突

rebase 过程中发生冲突,Git 会提示:

CONFLICT (content): Merge conflict in file.txt

解决步骤:

  1. 手动解决冲突,修改相关文件。
  2. 标记已解决
    git add <冲突文件>
  3. 继续 rebase
    git rebase --continue
  4. 如果不想继续 rebase,可以取消
    git rebase --abort

4. git rebase 高级用法

变基远程分支

git checkout feature-branchgit fetch origingit rebase origin/main

适用于: 让本地 feature-branch 基于最新的 main

将分支变基到另一分支

git rebase --onto new-base old-base feature-branch

等价于:

  1. 找到 feature-branch 相对于 old-base 的提交

  2. 将这些提交应用到 new-base

示例

当前 git log

A---B---C (old-base) \\ D---E---F (feature-branch)

执行

git checkout feature-branchgit rebase --onto new-base old-base

变为:

A---B---C (old-base) \\ X---Y---Z (new-base) \\  D\'---E\'---F\' (feature-branch)

即:feature-branchnew-base 继续,而不再基于 old-base

合并多个分支提交

git checkout feature-branchgit rebase --onto main develop feature-branch

这会把 feature-branch 上相对于 develop 的提交,变基到 main 分支上。

5. rebase 发生问题时的撤销

操作 作用 git rebase --abort 取消 rebase,回到原来的状态。 git rebase --continue 解决冲突后继续 rebasegit rebase --skip 跳过当前冲突的提交,继续 rebase

总结

命令 作用 git rebase main 让当前分支基于 main 重新整理提交。 git rebase -i HEAD~3 交互式修改最近 3 次提交。 git pull --rebaserebase 方式拉取远程更新,避免 merge commitgit rebase --onto new-base old-base feature-branchfeature-branchold-base 变基到 new-basegit rebase --abort 取消 rebase 并回到原状态。

cherry-pick

git cherry-pick 是 Git 中用于 选择性应用某个或多个提交 的命令。它允许你从一个分支中挑选特定的提交并应用到当前分支,而不需要合并整个分支。

1. 用法

git cherry-pick <commitHash>

git cherry-pick命令的参数,不一定是提交的哈希值,分支名也是可以的,表示引入该分支的最新提交

# 将feature分支的最近一次提交,引入到当前分支git cherry-pick feature

2. 提交多个hash

git cherry-pick <start-commit-hash>^..<end-commit-hash>
  • 是起始提交的哈希值。
  • 是结束提交的哈希值。

示例

git cherry-pick a1b2c3d4^..d4e5f6g7

这会挑选从 a1b2c3d4 开始到 d4e5f6g7 的所有提交。

2.1 挑选一组不连续的提交

git cherry-pick <commit-hash1> <commit-hash2> <commit-hash3># 示例git cherry-pick 1a2b3c4d 5e6f7g8h 9i0j1k2l

2.2 暂停的 Cherry-Pick

如果你在挑选多个提交时发生冲突,可以使用以下命令进行恢复或终止:

  1. 查看当前的 Cherry-Pick 状态:
    git status
  2. 如果解决了冲突,继续 Cherry-Pick:
    git cherry-pick --continue
  3. 如果放弃 Cherry-Pick:
    git cherry-pick --abort

3. cherry-pick 选项

3.1 -e / --edit

# 在提交前允许修改提交信息git cherry-pick -e <commit-hash>

3.2 -n / --no-commit

只应用更改,不创建新的提交。这允许你将多个提交的更改合并到一个提交中:

git cherry-pick -n <commit-hash>

示例:

  1. 挑选多个提交,但不提交
    git cherry-pick -n 1a2b3c4d 5e6f7g8h
  2. 合并这些更改并创建一个提交
    git commit -m \"Combined changes from specific commits\"

3.3 -x

在生成的提交信息中添加原始提交的引用,方便追溯

git cherry-pick -x <commit-hash># 生成的提交信息会附加类似以下内容(cherry picked from commit 1a2b3c4d)

rm

git rm 是 Git 中用于 移除文件 的命令。通过此命令,可以将文件从 工作区 和 暂存区 一并删除,同时记录删除操作以便在下次提交时生效。

1. 常用操作

1.1 删除文件并将其从暂存区移除

# 1. 从 暂存区 和 工作区 一并移除文件# 2. 下次提交后,删除会被记录在 Git 历史中git rm <file># 示例git rm file.txtgit commit -m \"Remove file.txt\"

1.2 只从暂存区移除文件,保留本地文件

# 文件从 暂存区 移除,但仍保留在本地工作区中# 通常用于将文件从版本控制中忽略(例如文件已错误地加入版本控制)git rm --cached <file># 示例git rm --cached config.jsongit commit -m \"Stop tracking config.json\"

2. 选项详解

2.1 --cached

只从暂存区移除文件,不删除工作区中的文件。
适用场景:

  • 停止跟踪某个文件,但不删除本地文件。
  • 通常与 .gitignore 配合使用。

示例

git rm --cached file.txt

2.2 -f--force

强制删除文件,适用于已修改且未提交的文件
默认行为:

  • 如果文件被修改但未提交,git rm 会报错以保护未保存的更改。
  • 使用 -f 可以跳过此保护。
    git rm -f file.txt

2.3 -r

递归删除目录及其内容。
适用场景:

  • 删除整个目录时,必须使用 -r。

3. 注意事项

3.1 删除的文件如何恢复?

如果误删了文件,可以通过 git checkoutgit restore 恢复:

  1. 如果文件还在版本控制中
    git restore file.txt
  2. 如果文件已经被提交删除
    git checkout <commit-hash> -- file.txt

3.2 .gitignore 的配合使用

删除文件后,如果希望 Git 永久忽略文件,可以将其加入 .gitignore 文件
操作步骤:

  1. 停止跟踪文件:
    git rm --cached file.txt
  2. 将文件加入 .gitignore
    echo \"file.txt\" >> .gitignore
  3. 提交更改:
    git add .gitignoregit commit -m \"Ignore file.txt\"

总结

# 删除单个文件git rm old_file.txtgit commit -m \"Remove old_file.txt\"# 删除整个目录git rm -r old_directorygit commit -m \"Remove old_directory\"# 从暂存区移除文件但保留本地文件git rm --cached config.jsongit commit -m \"Untrack config.json\"

tag

在 Git 中,标签(Tag) 是用来给特定的提交点打上一个易于识别的标记,通常用于标识版本(如 v1.0.0)。

1. 查看现有标签

git tag

2. 创建附注标签

git tag -a <tag_name> -m \"\"

例如

git tag -a v1.0.0 -m \"Release version 1.0.0\"

3. 给特定的提交打标签

默认情况下,标签会打在当前的提交上。如果需要给某个特定的提交打标签,可以指定提交的哈希值。

git tag <tag_name> <commit_hash>

例如

git tag v1.0.0 9fceb02git tag -a v1.0.0 9fceb02 -m \"Release version 1.0.0\"

4. 推送标签到远程仓库

创建的标签默认只存在于本地,需要手动推送到远程仓库。

  • 推送单个标签:
    git push origin <tag_name>

    例如

    git push origin v1.0.0
  • 推送所有标签:
    git push origin --tags

5. 删除标签

  • 删除本地标签
    git tag -d <tag_name>

    例如

    git tag -d v1.0.0
  • 删除远程标签
    git push origin --delete <tag_name>

    例如

    git push origin --delete v1.0.0

6. 检查标签详细信息

git show <tag_name>

7. 拉取标签

默认情况下,执行 git fetch 命令时,Git 不会自动拉取标签。需要显式指定拉取标签。

拉取所有标签

git fetch --tags

8. 拉取标签和代码的区别

  • 如果你只想拉取标签,不同步代码
    git fetch origin --tags
  • 如果你想拉取所有代码和标签
    git pull --tags

9. 检出到某个标签

标签本身是静态的快照,不能直接修改代码。要检出到一个标签对应的提交,可以运行以下命令

git checkout <tag_name>

例如

git checkout v1.0.0

注意:检出标签后,Git 会进入 分离头指针状态(detached HEAD),你无法直接提交新代码。如果需要修改代码,可以创建一个新分支:

git checkout -b <new_branch_name>

stash

git stash 是 Git 中用于临时保存当前工作进度的命令。它特别适用于需要切换分支或者处理其他紧急任务时,不想丢失当前未提交的修改。下面我会详细介绍 git stash 的用法和常见场景。

git stash

这个命令会将当前工作目录和暂存区的更改(包括已暂存和未暂存的)保存起来,并恢复工作区到最近一次提交的状态。

未跟踪文件:git stash 默认只会保存已跟踪的文件的修改,不会保存新创建的未跟踪文件。如果你希望同时保存未跟踪文件,需要使用 git stash -u(或者 git stash --include-untracked)。

# 执行后,Git 会把当前的修改保存到栈中,并清空工作目录和暂存区。git stash# 默认情况下,git stash 只会保存已跟踪文件的更改。# 如果你有一些未跟踪的文件(如新创建的文件),可以使用 -u 参数将它们也一起保存。git stash -u# 你可以在保存时给 stash 添加一个描述信息,这有助于你以后更好地识别每个 stash。git stash save \"修复登录页面的样式\"

git stash list

这个命令会列出所有的 stash 条目,每个 stash 条目都有一个编号 stash@{n}n 从 0 开始递增

git stash list# 输出stash@{0}: WIP on master: 6b1d3e5 修复登录页面样式stash@{1}: WIP on dev: 9a8b2f4 添加功能模块

git stash show

查看某个 stash 的详细内容。你可以使用 stash@{n} 来查看特定的 stash。

git stash show stash@{0}# 如果你想查看更详细的差异信息,可以加上 -p 参数:git stash show -p stash@{0}

git stash apply

将某个 stash 应用到当前工作目录。应用时,stash 并不会从栈中删除,它仍然保留。

git stash apply \"stash@{1}\"# 如果你想应用最新的 stash,可以省略 stash@{n},直接使用:git stash apply 1

git stash pop

类似于 git stash apply,但是会把应用的 stash 从栈中删除。通常用于你确认不再需要该 stash 时。

git stash pop

git stash drop stash@{n}

删除指定的 stash 项目。

git stash drop \"stash@{0}\"

git stash clear

清空所有的 stash 项目。

git stash clear

log

常用命令

# 查看最近一个周的提交日志git log --pretty=format:\'%h %ad %an %s\' --author=xxx --since=7.days# 格式化日志并展示所有提交git log --pretty=format:\'%h %ad %an %s\' --graph --all -20# 表格显示所有提交git log --graph -all -2
git log --oneline# 示例1234567 Initial commitabcdef1 Add README file789abcd Fix bug in calculation#查看从 2024 年 11 月 1 日到 2024 年 11 月 20 日的提交记录。git log --since=\"2024-11-01\" --until=\"2024-11-20\"# 查看最近三天提交git log --since=\"3 days ago\"# 或者git log --since=3.days

查看特定文件的提交记录

git log <文件名># 示例git log README.md

查看某个分支的提交记录

git log branch-name# 示例git log feature-branch

显示提交历史的分支结构

git log --graph# 示例git log --oneline --graph --all# 输出* 789abcd (HEAD -> main) Fix bug in calculation| * abc1234 (feature-branch) Add new feature|/* 1234567 Initial commit

统计提交次数

  • 统计最近一周内每个人的提交次数:
    git shortlog -s -n --since=\"1 week ago\"

    输出:

    10 Alice 5 Bob 3 Charlie
  • 统计某个用户的提交次数:
    git log --author=\"Alice\" --since=\"1 week ago\" --oneline | wc -l

仅查看文件变更

查看最近 7 天内修改的文件:

git log --since=\"7 days ago\" --name-only --pretty=format:\"\"

格式化日志

自定义格式

git log --pretty=format:\"%h - %an, %ar : %s\"
  • %h:提交短哈希。
  • %an:作者名。
  • %ar:相对时间(如 “2 weeks ago”)。
  • %s:提交信息。
  • %ad: 当前时间
git log --pretty=format:\"%h %an %ad %s\" --date=short# 输出1234567 Alice 2024-11-20 Initial commitabcdef1 Bob 2024-11-19 Add README file

结合 grep 搜索提交

git log --grep=\"关键字\"# 示例git log --grep=\"fix\"git log --author=\'作者\'

全面查看提交历史

查看所有分支的提交历史(简洁格式 + 图形化 + 全部分支)

git log --oneline --graph --all# 查看最近 10 条提交的详细改动内容git log -p -n 10

查看提交内容

# 显示一条的提交差异git log --patch -1# 或git log -p -1# 显示修改行数git log --stat -1

总结

功能 命令 查看默认提交记录 git log 简洁模式查看 git log --oneline 查看提交改动内容 git log -p 查看文件的提交记录 git log 查看提交行数统计 git log --stat 查看分支结构 git log --graph 自定义格式化日志 git log --pretty=format:\"%h - %an, %ar : %s\" 搜索特定关键词提交 git log --grep=\"关键字\"

show和diff 区别

git showgit diff 都是用来查看代码变更的 Git 命令,但它们的用途和输出内容有所不同。

git show

  • 用途: 用于显示某个特定提交的详细信息,包括提交的元数据(提交信息、作者、日期)以及该提交的具体变更(修改了哪些文件,哪些行被修改)。
  • 输出内容:
    • 提交的哈希值、作者、日期、提交信息等元数据。
    • 提交中修改的文件及其具体的变更(即显示 diff
  • 常见用法:
    • 查看某个特定提交的详细内容
      git show <commit_id>
    • 仅查看提交的文件修改(不包括提交信息等元数据)
      git show --name-only <commit_id>
    • 查看提交的改动统计
      git show --stat <commit_id>
  • 适用场景: 当你已经知道某个提交的哈希值,并且想查看该提交的详细内容(包括哪些文件被修改,以及每个文件的变更)。
  • 示例:
    # 这将展示提交 8a3cdef3e8c58b1cbe3d4f46b0c8ed6e0e63d3d5 的详细信息,包括文件变更和具体差异。git show 8a3cdef3e8c58b1cbe3d4f46b0c8ed6e0e63d3d5

git diff

  • 用途: 用于显示当前工作区(工作目录)与暂存区之间、暂存区与当前分支的最新提交之间的差异,或者显示两个提交之间的差异。常用于查看未提交的更改。
  • 输出内容: 显示差异(diff),即哪些行发生了变动,+ 表示新增,- 表示删除。
  • 常见用法:
    • 查看工作目录与暂存区之间的差异(未暂存的更改)
      git diff
    • 查看暂存区与最新提交之间的差异
      git diff --cached
    • 查看两个特定提交之间的差异
      git diff <commit_id_1> <commit_id_2>
    • 查看某个提交与当前工作区之间的差异
      git diff <commit_id>
  • 适用场景: 当你想查看当前工作目录、暂存区或两个提交之间的差异时。
  • 示例:
    # 这将显示当前工作目录与最新提交(HEAD)之间的差异,展示哪些行在本地还没有提交。git diff HEAD

区别总结

命令 用途 输出内容 适用场景 git show 查看某个提交的详细信息(包括提交元数据和变更内容) 提交元数据(哈希、作者、日期、提交信息等)和变更(文件和具体差异) 查看某个提交的详细内容 git diff 查看工作区和暂存区、或两个提交之间的差异 仅显示文件间的差异,逐行显示哪些内容被修改,新增或删除 查看未提交的更改、工作目录与暂存区的差异等
  • git show 是查看某个提交的详细信息,包括元数据和文件差异。
  • git diff 更关注查看未提交的更改,或查看两个提交之间的差异。

submodule

Git 中,子仓库(Submodule)是一种在一个 Git 仓库中嵌套另一个 Git 仓库的机制,适用于需要将一个项目的某些部分独立管理的场景。子仓库通常被用来管理项目的依赖关系或共享代码库。

什么是子仓库?

子仓库是一个 Git 仓库,作为另一个 Git 仓库(称为主仓库)的子目录存在。每个子仓库都维护自己独立的版本历史和分支,并被主仓库引用为一个特定的提交(类似于快照)。

常用操作

1.添加子仓库

git submodule add <子仓库地址> <路径># 例如git submodule add https://github.com/example/library.git libs/library
  • 是子仓库的远程地址。
  • 是子仓库在主仓库中的存放目录。

执行后会:

  1. 在主仓库目录下创建一个指向子仓库的文件夹。
  2. .gitmodules 文件中记录子仓库信息。

2. 初始化子仓库

当从其他开发者处克隆包含子仓库的主仓库时,子仓库不会自动初始化。需要以下步骤

git submodule initgit submodule update
  • git submodule init:根据 .gitmodules 文件注册子仓库信息。
  • git submodule update:下载子仓库的代码并检出到指定版本。

3. 更新子仓库

当子仓库有新提交时,可以拉取最新代码

cd <子仓库路径>git pull origin <分支名>

4. 删除子仓库

如果需要从主仓库中移除子仓库,可以按以下步骤操作:

  1. 删除子仓库的引用和文件:
git submodule deinit -f <子仓库路径>rm -rf .git/modules/<子仓库路径>rm -rf <子仓库路径>
  1. 从 .gitmodules 文件和 .git/config 文件中删除相关配置。

.gitmodules 文件详解

主仓库会通过 .gitmodules 文件记录子仓库信息。文件内容示例:

[submodule \"libs/library\"] path = libs/library url = https://github.com/example/library.git
  • path 指定子仓库存放路径。
  • url 指定子仓库的远程地址。

常见问题

子仓库未初始化如何解决?

# --recursive 参数会递归初始化所有嵌套子模块。git submodule update --init --recursive

取消子仓库在主仓库中的未追踪中展示

修改 .gitmodules 文件中的配置
.gitmodules 中,可以为子模块设置 ignore 属性,让 Git 忽略子仓库的变动。步骤如下:

  1. 编辑 .gitmodules 文件:
    git config -f .gitmodules submodule.<子模块路径>.ignore all

    或直接手动修改 .gitmodules 文件,添加以下内容:

    [submodule \"子模块路径\"] path = 子模块路径 url = 子模块的远程地址 ignore = all
  2. 更新 Git 配置
    git submodule update --init --recursivegit add .gitmodulesgit commit -m \"配置子模块忽略变动\"

问题记录

Gitee exceeds quota 100MB

你推送的单个文件超过了 Gitee 的 100MB 限制(免费用户限制单个文件不能超过100MB)

你可以运行以下命令查看 Git 历史中有哪些大文件:

git rev-list --objects --all | sort -k 2 > allfiles.txt

然后查看 allfiles.txt,用文本编辑器打开,找出大于 100MB 的文件。