Loading...

文章背景图

Git

2025-04-02
0
-
- 分钟
|

尚且注意,这个 bash 命令行是类 unix 的所以 window 的路径中的斜杠要修改为反斜杠才能识别正确路径,进入 D 盘的命令为

cd /d/

查看提交的所有次数

git rev-list --count HEAD

Git 命令大全

全局配置

git config --global user.name "用户名" # 设置全局用户名
git config --global user.email "邮箱" # 设置全局邮箱
git config --global core.editor "编辑器命令" # 设置默认文本编辑器
git config --global init.defaultBranch main # 设置默认分支名
git config --list # 列出所有配置
git config user.name # 查看当前用户名
git config --global alias.<别名> '命令' # 设置命令别名

仓库操作

git init # 初始化本地仓库
git clone <仓库地址> # 克隆远程仓库到本地
git clone --depth 1 <仓库地址> # 浅克隆(只下载最近一次提交)
git remote add origin <仓库地址> # 关联远程仓库
git remote -v # 查看远程仓库信息
git remote show origin # 查看远程仓库详细信息
git remote set-url origin <新地址> # 修改远程仓库地址
git remote remove origin # 删除远程仓库关联

工作区与暂存区

git status # 查看工作区状态
git status -s # 简洁状态显示
git add <文件名> # 将指定文件添加到暂存区
git add . # 将所有修改添加到暂存区
git add -A # 添加所有修改(包括删除的文件)
git add -p <文件名> # 交互式添加文件部分修改
git rm <文件名> # 删除文件并添加到暂存区
git rm --cached <文件名> # 从暂存区移除文件(保留本地文件)
git mv <原文件名> <新文件名> # 重命名文件并添加到暂存区,也能重命令暂存区的文件
git restore <文件名> # 撤销工作区的修改(Git 2.23+)
git restore --staged <文件名> # 将文件从暂存区撤出(Git 2.23+),并撤销工作区的修改
git checkout -- <文件名> # 丢弃工作区的修改
git reset HEAD <文件名> # 将暂存区的修改撤销到工作区

提交操作

git commit -m "提交信息" # 提交暂存区到本地仓库
git commit -am "提交信息" # 直接提交已跟踪文件的修改(跳过 add)
git commit --amend # 修改最近一次提交(未推送到远程时使用),注意要先将要添加或者修改的文件放入暂存区,但是这个过程可能会很久
git commit --amend "修改最近一次的提交信息"
git commit --amend --no-edit # 修改最近一次提交,但不修改提交信息
git commit --allow-empty -m "提交信息" # 允许空提交

分支操作

git branch # 查看本地分支
git branch -r # 查看远程分支
git branch -a # 查看所有分支(本地 + 远程)
git branch -vv # 查看分支详细信息(包括跟踪关系)
git branch <分支名> # 创建新分支
git checkout <分支名> # 切换到指定分支
git switch <分支名> # 切换到指定分支(Git 2.23+)
git checkout -b <分支名> # 创建并切换到新分支
git switch -c <分支名> # 创建并切换到新分支(Git 2.23+)
git merge <分支名> # 将指定分支合并到当前分支
git merge --no-ff <分支名> # 合并分支时禁用快进(Fast-forward)模式
git branch -d <分支名> # 删除本地分支(需先合并)
git branch -D <分支名> # 强制删除本地分支(未合并也可删)
git push origin --delete <分支名> # 删除远程分支
git branch -m <新分支名> # 重命名当前分支
git branch -m <旧分支名> <新分支名> # 重命名指定分支

远程同步

git fetch # 从远程仓库下载最新数据,但不合并
git fetch --prune # 获取远程更新并清理已删除的远程分支
git fetch origin <分支名> # 获取远程指定分支的更新
git pull # 拉取远程仓库更新并合并到本地
git pull origin <分支名> # 拉取指定远程分支并合并
git pull --rebase # 拉取远程更新并使用变基方式合并
git push # 推送本地提交到远程仓库
git push origin <分支名> # 推送本地分支到远程
git push -u origin <分支名> # 推送并关联远程分支(首次推送新分支用)
git push -f # 强制推送(谨慎使用,会覆盖远程历史)
git push --force-with-lease # 强制推送,但不会覆盖他人的提交(比-f安全)

历史查看

git reflog # 查看所有操作记录(包括已删除的提交)
git log # 查看提交历史
git log --oneline # 简洁显示提交历史
git log --graph # 图形化显示分支合并历史
git log --all # 查看所有分支的提交历史
git log --author="用户名" # 查看指定作者的提交
git log --since="2024-01-01" --until="2024-01-31" # 查看指定时间段的提交
git log --grep="关键词" # 搜索提交信息中的关键词
git log -p # 显示每次提交的详细差异
git log --graph --oneline --all --decorate # 图形化展示所有分支,显示简洁提交信息和标签/分支指向
git log --pretty=format # "%h - %an, %ar  #  %s" # 自定义格式显示(哈希、作者、相对时间、提交信息)
git log --since=1.weeks --pretty=oneline # 显示最近1周的提交(支持1.day/1.month)
git log -p <文件名> # 查看指定文件的历史修改记录(包含具体变更内容)
git log --stat # 显示每个提交的文件修改统计(增删行数)
git log --name-only # 显示每个提交修改的文件名列表
git log --author="用户名" --grep="关键词" # 查找指定作者且提交信息含关键词的记录
git log -n 5 # 只显示最近5条提交
git log <分支1>..<分支2> # 查看分支2比分支1多的提交
git log --left-right <分支1>…<分支2> # 对比两个分支的差异(左为分支1独有的,右为分支2独有的)
git show <提交哈希> # 显示某次提交的详细信息
git blame <文件名> # 逐行显示文件的修改历史和作者
git shortlog # 按作者分组显示提交历史
git whatchanged # 查看文件变更历史

版本回退

git reset --hard <提交哈希> # 回退到指定版本(彻底丢弃之后的提交)
git reset --soft <提交哈希> # 回退到指定版本(保留修改在暂存区)
git reset --mixed <提交哈希> # 回退到指定版本(保留修改在工作区,默认行为)
git clean -nfd # 查看将被删除的未追踪文件和目录
git clean -fd # 删除未追踪的文件和目录
# 所以,git reset --hard 和 git clean -fd 是一对黄金搭档,它们共同协作,才能将你的本地工作区完完全全地重置到一个指定的历史提交状态

git revert <提交哈希> # 创建新提交来撤销指定提交的修改(安全,不改变历史)
git revert --no-commit <提交哈希> # 撤销但不自动提交,可以多次撤销然后一起提交
git revert -n <提交哈希> # 同上,撤销但不提交

变基操作

git rebase <分支名> # 将当前分支变基到指定分支
git rebase --interactive <提交哈希> # 交互式变基(可以修改、合并、删除提交)
git rebase --continue # 继续变基(解决冲突后)
git rebase --abort # 终止变基操作,回到变基前的状态
git rebase --skip # 跳过当前提交(在交互式变基中)

暂存工作区

git stash # 暂存当前工作区的修改
git stash save "备注信息" # 带备注暂存
git stash list # 查看所有暂存记录
git stash apply <stash@{n}> # 应用指定暂存(不删除暂存记录)
git stash pop # 应用最近的暂存并删除记录
git stash drop <stash@{n}> # 删除指定暂存记录
git stash clear # 清空所有暂存
git stash show -p <stash@{n}> # 显示指定暂存的详细修改内容
git stash branch <新分支名> <stash@{n}> # 从暂存创建新分支

标签操作

git tag # 查看所有标签
git tag <标签名> # 创建轻量标签
git tag -a <标签名> -m "标签说明" # 创建带注释的标签
git tag -a <标签名> <提交哈希> # 在指定提交上打标签
git show <标签名> # 查看标签信息
git push origin <标签名> # 推送标签到远程
git push origin --tags # 推送所有标签到远程
git tag -d <标签名> # 删除本地标签
git push origin --delete <标签名> # 删除远程标签

子模块

git submodule add <仓库地址> <路径> # 添加子模块
git submodule init # 初始化子模块
git submodule update # 更新子模块
git submodule update --init --recursive # 递归初始化并更新子模块
git submodule foreach '命令' # 在每个子模块中执行命令

高级操作

git bisect start # 开始二分查找
git bisect bad # 标记当前提交为有问题
git bisect good <提交哈希> # 标记某提交为正常
git bisect reset # 结束二分查找
git worktree add <路径> <分支名> # 添加工作树
git worktree list # 列出所有工作树
git cherry-pick <提交哈希> # 选择某个提交应用到当前分支
git filter-branch # 重写分支历史(谨慎使用)
git fsck # 检查仓库完整性

清洁 git 仓库

这里是清洁所有的记录,我们并不推荐

git reflog # 查看所有操作记录(包括已删除的提交)
git clean -fdx # 清理工作区所有未追踪/忽略的文件(彻底清空工作区冗余)
git reflog expire --expire=now --all # 删除找回旧提交的 “线索”
git gc --prune=now --aggressive # 删除 Git 仓库中存储的旧提交 / 缓存数据
git reflog # 查看所有操作记录(包括已删除的提交)

这里展示只保留我们要的记录,清空其他的记录数据,但是有点麻烦

# 清除特定的一条信息
git reflog delete HEAD@{0}

# 1. 强制过期所有旧 reflog
git reflog expire --expire=all --all

# 2. 清理所有不可达的对象
git reflog expire --expire-unreachable=now --all

# 3. 垃圾回收 + 彻底删除所有隐藏历史
git gc --prune=now --aggressive

# 4. 重置 HEAD 引用(彻底消除隐藏操作痕迹)
git update-ref HEAD $(git rev-parse HEAD)

忽略文件

# .gitignore 文件示例
*.log
node_modules/
.DS_Store
.env
dist/
build/

差异比较

git diff # 比较工作区和暂存区的差异
git diff --staged # 比较暂存区和最新提交的差异
git diff HEAD # 比较工作区和最新提交的差异
git diff <分支1> <分支2> # 比较两个分支的差异
git diff --name-only # 只显示有差异的文件名
git diff --cached # 同 --staged

我将在你提供的 Git 命令大全基础上,补充关于撤销本地和远程提交的相关命令:

撤销提交操作

撤销本地提交上一次提交

git reset --mixed <提交哈希> # 哈希值填写,倒数第二次提交,即上一次提交之前

然后重新提交即可

撤销远程提交

# 方法1: 使用revert(推荐,不改变历史,安全)
# 撤销远程最近一次提交,会创建一个新的撤销提交
git revert HEAD
git push origin <当前分支名>

# 撤销远程上上次提交
git revert HEAD~1
git push origin <当前分支名>

# 撤销远程指定提交
git revert <提交哈希>
git push origin <当前分支名>

# 方法2: 使用reset + 强制推送(危险,会改写历史,团队协作中慎用)
# 1. 先本地撤销到目标提交
git reset --hard <目标提交哈希>
# 2. 强制推送到远程(会覆盖远程历史)
git push -f origin <当前分支名>

# 更安全的强制推送方式(如果有其他人提交会失败)
git push --force-with-lease origin <当前分支名>

完整安全提交步骤:

我们需要利用分支安全的操作

  1. 在主分支暂存所有修改
    先在 master 分支将当前所有修改(包括新增、修改、删除的文件)添加到暂存区,确保工作区的变更被暂存:(这一步的目的是:让后续新建的临时分支能完整继承这些暂存的修改,避免遗漏)

    git checkout master  # 确保当前在主分支
    git add -A           # 暂存所有变更(-A 等价于 --all,包含删除的文件)
    
  2. 新建临时分支并隔离状态
    基于当前 master 分支的暂存状态,新建并切换到临时分支(此时临时分支会包含主分支的所有暂存修改):

    git checkout -b safe-temp-branch  # 新建分支并切换,自动继承暂存区内容
    
  3. 在临时分支提交并验证钩子
    在临时分支执行提交,不跳过钩子(以此验证钩子是否正常,避免直接污染主分支):

    git commit -m "临时保存:验证钩子及当前状态"  # 正常触发 pre-commit、commit-msg 等钩子
    
    • 若提交成功:说明钩子逻辑没问题,当前修改的格式、规范等符合要求。

    • 若提交失败:钩子检测到问题(如代码格式错误、提交信息不规范等),此时直接在 safe-temp-branch 分支修改问题(比如调整代码格式、修改提交信息模板),然后重新提交:

      # 修复问题后重新暂存并提交(仍在临时分支)
      git add -A  
      git commit -m "修复钩子问题:调整格式/规范"  
      

      反复验证直到提交成功,确保钩子不再报错。

  4. 切换回主分支并合并验证后的修改
    确认临时分支的提交和钩子都正常后,切换回主分支,将临时分支的修改合并过来:

    git checkout master  # 回到主分支(此时主分支仍保持合并前的纯净状态)
    git merge safe-temp-branch  # 合并临时分支的所有验证通过的修改
    
    • 若合并时出现冲突(如主分支在你操作期间有其他人提交了修改):
      手动解决冲突文件(文件中会用 <<<<<<< ======= >>>>>>> 标记冲突区域),解决后执行 git add -Agit commit -m "合并 safe-temp-branch 并解决冲突" 完成合并。

  5. 清理临时分支
    合并完成且确认主分支状态正常后,删除临时分支(避免仓库分支冗余):

    git branch -d safe-temp-branch  # 删除已合并的临时分支
    

(若提示分支未合并,可先确认是否真的已合并,确认后用 git branch -D safe-temp-branch 强制删除)

创建并切换到新分支,将这次分支保留,然后回到主分支

要将当前修改提交到新分支,可按以下步骤操作:

  1. 创建并切换到新分支
    首先创建一个新分支(例如命名为 study-original,可根据需求修改),并自动切换到该分支:

    git checkout -b study-original
    

-b 选项表示创建并切换分支,study-original 是新分支的名称,可自定义)

  1. 暂存当前修改
    将工作区的所有修改暂存(如果只需暂存特定文件,将 . 替换为文件名即可):

    git add .
    
  2. 提交修改到新分支
    用指定的提交信息提交暂存的修改(避免使用我们设定好的钩子函数):

    git commit --no-verify -m "学习原项目,无果"
    

完成后,当前修改就会被提交到新创建的 study-original 分支中了。

  1. 切换到 master 分支后,就可以继续主分支学习了

git checkout master

妙用

具体步骤(生成「操作日志.md」)

假设目标分支为 target-branch,目标文件为 path/to/file.txt,整合后的文件为「操作日志.md」,操作如下:

1. 获取该文件的所有提交哈希(按时间正序排列)

# 切换到目标分支(或直接在命令中指定分支,如:git log target-branch -- …)
git checkout target-branch

# 获取所有修改过该文件的提交哈希(按时间倒序),反转后为「最早→最新」
commits=$(git log --pretty=format:%H -- README.md | tac)

2. 遍历提交,提取内容并追加到「操作日志.md」

#!/usr/bin/env bash
set -euo pipefail

# 导出指定文件在当前分支(默认 HEAD)的历史快照(考虑重命名)到 README_Overall.md
# 用法:
#   bash tools/export_file_history.sh                 # 默认 README_Section.md
#   bash tools/export_file_history.sh src/main.ts     # 指定文件

FILE=${1:-README.md}
OUT="README_Overall.md"

# 确定 HEAD 时刻的文件路径(处理重命名)
HEAD_PATH="$FILE"
# 检查 HEAD 中是否存在该文件(处理当前名称)
if ! git cat-file -e "HEAD:$FILE" 2>/dev/null; then
  # 查找最近一次涉及该文件的路径(含重命名历史)
  maybe=$(git log -n1 --follow --name-only --pretty="" -- "$FILE" || true)
  if [ -n "${maybe:-}" ]; then
    HEAD_PATH=$(printf "%s\n" "$maybe" | head -n1)
  fi
fi

# 验证最终路径是否存在提交历史
if ! git log --pretty=format:%H -n1 -- "$HEAD_PATH" 2>/dev/null; then
  echo "错误:文件 '$HEAD_PATH' 没有提交历史"
  exit 1
fi

printf '# %s 历史快照汇总\n' "$HEAD_PATH" > "$OUT"

# 获取所有相关提交(按时间正序),使用 readarray 确保完整读取
readarray -t commits < <(git log --follow --reverse --pretty=format:%H -- "$HEAD_PATH")

# 循环处理每个提交
for commit in "${commits[@]}"; do
  {
    echo
    printf '## 提交: %s\n' "$commit"
    printf -- '- 作者: %s\n' "$(git log -1 --pretty=format:%an "$commit")"
    printf -- '- 时间: %s\n' "$(git log -1 --date=iso-strict --pretty=format:%cd "$commit")"
    echo '---'
    # 获取该提交中文件的实际路径(处理重命名)
    # 使用 git log 而非 git show 以提高路径解析可靠性
    commit_path=$(git log -1 --name-only --pretty="" "$commit" -- "$HEAD_PATH" | head -n1 || true)
    if [ -n "${commit_path:-}" ]; then
      # 尝试获取该提交中的文件内容
      if git cat-file -e "$commit:$commit_path" 2>/dev/null; then
        git show "$commit:$commit_path"
      else
        echo "(该提交中文件内容不可用)"
      fi
    else
      echo "(该提交中未找到文件记录)"
    fi
    echo
  } >> "$OUT"
done

echo "已生成: $OUT"

评论交流

文章目录