目录

Git笔记

目录

一、git概述

  1. Git 是一个开源的分布式版本控制系统,是 Linus Torvalds为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
  2. git基本概念
    • 工作区 任何当前所做的临时改动都在工作区
    • 暂存区 add之后到暂存区
    • 本地仓库 commit之后到本地仓库
    • 远程仓库 push之后到远程仓库
  3. 强烈建议所有的git仓库都有README, LICENSE, .gitignore三个文件

二、git核心命令

(一) Git 全局设置:

git config --global pull.rebase true                        #配置库默认使用 pull --rebase
git config --global user.name "nickname"                    #配置提交用户名
git config --global user.email "XXX@mail.com"               #配置邮箱
git config --global core.excludesFile C:\Users\root\.gitignore  #配置全局忽略文件夹
git config --global gui.encoding utf-8                      #设置图形化界面编码为utf-8
git config --global http.proxy http://127.0.0.1:7890                 #设置当前代理
git config --global https.proxy http://127.0.0.1:7890                 #设置当前代理
git config --global --unset http.proxy                      #取消全局代理
git config --unset http.proxy                               #取消当前代理
git config http.proxy socks5://127.0.0.1:7890               #设置socks5代理
git config --global branch.autosetuprebase always           #设置默认以rebase方式pull
git config core.longpaths true                              #启用长路径(clone时文件长路径,报fatal: cannot create directory:xx: Filename too long)
git config --get core.longpaths                             #获取配置信息(--get可省略)

(二) 常规操作

  1. 初始化仓库
git init
  1. 添加文件到Git仓库
git add <file>                                              #提交到暂存区

git add .                                                   #添加所有文件到暂存区,但不包括被删除文件

git add -u                                                  #提交已被跟踪的所有文件到暂存区,但不包括新建的文件

git add -A                                                  #添加所有文件改动到暂存区,包括删除的和新建的



git commit -m <message>                                     #提交到本地仓库

git commit --amend [--no-edit]                              #修正上回提交,可修改提交信息(已推送到远程则不要用这个命令,避免不必要的麻烦)

git commit --allow-empty-message                            #提交到本地仓库但不带描述信息
  1. 分支操作
git branch -a                                           #查看所有分支,包括远程分支

git branch <name>                                       #创建分支

git branch -d <branch-name>                             #删除分支

git branch -D <branch-name>                             #强制删除

git checkout <name> 或 git switch <name>                #切换分支
git checkout -b <name> 或 git switch -c <name>          #创建并切换到新分支

git checkout -b feat1 remotes/origin/feat1              #创建远程分支的本地分支



git merge --no-ff -m "merge with no-ff" <name>              # 推荐方式(合并后可看到被合并的分支)

git merge <name>                                            # 默认方式(合并看不到分支,看不出曾做过合并。即--ff, 快进(fast-forward)方式) 
  1. 查看提交信息
git status                                                  #查看git工作区的状态

git show <commit-id>                                        #查看某个提交的详细信息
git log                                                     #显示所有提交过的版本信息
git log <filePath>                                          #显示指定文件的提交历史
git log --graph                                             #同上,多了分支合并图
git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' --all
git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'

git log --pretty='format:%C(auto)%h %as (%s, %ad %cn[%ce])'   # xxx 2025-04-21 (修改:xxx问题, Mon Apr 21 19:11:10 2025 +0800 提交人[xxx@xxx.com])
git log --pretty=oneline                                    #同上,但只会显示版本号和提交时的备注信息
git log --pretty=oneline path/filename


git log -p -L 8,27:data/tools.toml                          # 查看10~20行全部历史变更,附带diff
git log --reverse -p -L 8,27:data/tools.toml                # 代码历史变更,正序:从最早到最新,看代码一步步演化(适合溯源)
git log --reverse --author="root" -p -L 8,27:data/tools.toml  #指定作者
--since="2026-09-30" --until="2026-10-02"                     # 指定时间

git blame -L 8,27 data/tools.toml                           # 如果只想看当前行最后的提交信息

git reflog                                                  #显示所有分支的所有操作命令记录
  1. 从版本中删除文件
git rm <file>                                               #从工作区和暂存区中删除文件

git rm --cached <file>                                      #从暂存区中删除文件,工作区文件还在

git rm --cached -r <Directory>                              #从暂存区中删除文件夹,工作区文件还在
  1. 查看修改
git diff <file>                                             #查看当前没有add 的内容修改

git diff --cached                                           #查看已经add 没有commit 的改动 使用

git diff origin/分支名 HEAD                                 #查看未推送的详细改动(查看已commit和远程分支的区别)

git diff HEAD -- readme.txt                                 #可以查看工作区和commit版本库里面最新版本的区别

git diff --name-only 562d562ef7ab57bf7c1fe3d3a05abb4cff018d84 HEAD | xargs tar -zcvf diff.tar.gz  # 将差异文件打包

git diff fee9f9cf4b cdd577e352 app/build.gradle             #比较两次commit的指定文件差异,不指定文件则比较所有差异

git diff > xxx.patch                                        #将当前工作区修改的内容保存到patch文件中

git apply --stat xxx.patch                                  #查看patch文件内容

git apply --check xxx.patch                                 #检查patch文件是否正确

git apply xxx.patch                                         #应用patch文件
  1. 撤销修改
git checkout -- file   
#撤销工作区所有修改,若有修改添加到暂存区,则恢复暂存区修改版本到工作区
#若暂存区无记录则恢复工作区和本地版本库一致

git reset HEAD <file>  
#恢复最近一次提交的本地版本库的文件到暂存区,即把暂存区的修改撤销掉
#该操作不影响工作区,撤销git add

git  commit --amend    
#相当于上次提交错误的信息被覆盖。修改上一次提交(commit),将两次提交合并为一次提交。
#修改错误之后,执行该commit,可覆盖上次提交的注释及文件记录
#不要试图去修改已push到线上的记录
  1. 回退到上一个版本/指定版本
  • 在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,可写成HEAD~100。
git reset --hard HEAD^

git reset --hard <commit_hash>

(三) 远程仓库操作

  1. 从远程库克隆
git clone git@host:path/repo-name.git

git clone -b branch1 git@host:path/repo-name.git            # 克隆远程指定分支

git clone --depth 1 git@host:path/repo-name.git             # 浅克隆(仅克隆部分的存储库历史记录)
  1. 本地仓库关联远程仓库
git remote add origin git@host:path/repo-name.git

git remote set-url origin git@host:path/repo-name.git       #修改origin远程地址
  1. 推送本地dev分支到远程origin仓库
git push origin dev
  1. 删除远程dev分支
git push origin --delete dev
  1. 从远程库获取更新信息
git remote -v                                               #查看远程库的信息

git fetch                                                   #获取远程更新,但不合并分支

git pull                                                    #获取远程更新并合并分支,同“git fetch & git merge”

git pull --rebase                                           #获取远程更新并将本地提交放到远程代码最后

git checkout -t origin/remoteBranchName                     #在本地建立一个和远程分支名字一样的分支

git checkout -b localBranchName origin/remoteBranchName     #在本地建立远程分支内容的分支名为localBranchName的分支

(四) 标签操作

  1. 列出标签
git tag

git tag -l "通配符字符串"
  1. 创建标签
git tag v1.0.1                                           #给最新的提交打标签

git tag -a v1.4 -m "my version 1.4"                      #带附注的标签

git tag -a v1.2 <commit_hash>                            #给指定版本的提交打标签
  1. 提交标签到远程仓库
git push origin <tagname>
  1. 删除标签
git tag -d <tagname>                                    #删除本地标签

git push origin --delete <tagname>                      #删除远程仓库标签(1)

git push origin :refs/tags/<tagname>                    #删除远程仓库标签(2)

(五)进阶操作-待完善

  • git stash
    • git stash list
    • git stash pop 0
    • git stash drop 0
    • git stash -m “feat:xxx”
  • git rebase
  • git cherry-pick <commit_hash>

三、实践

  1. 合并分支
# 合并到master
git checkout dev

git pull

git checkout master

git merge dev

git push -u origin master


# 合并master更新到dev
git checkout master 

git pull 

git checkout dev

git merge master 

git push -u origin dev
  1. 回退到指定版本
git reset --hard  <commit_hash>                         #回退到指定版本

git push -f                                             #强制提交
  1. 强制提交dev后,和test分支不一致,分支污染–>分支回归一致
# 情况复现步骤:
#1. 用在dev提交feat1,且构建到test了
#2. 用户将DEV分支git reset --hard HEAD^回退后,开发了feat2后强制提交(git push -f)
#3. 此时dev和test处于不同的提交路径上,jenkins拒绝构建合并

[test] git revert <feat1_commit_hash>       # 如果需要在qa上修改,最后需要合并回dev才能正常提交jenkins构建(git merge --no-ff test)
[test] git merge --no-ff dev                # 把dev提交合并过来,两个分支就处于同一路径上了
[test] git push origin qa
  1. 回退新功能提交,保留fix提交
git log                                                 #查看之前新功能版本的<commit_hash>信息

git revert <commit_hash>                                  #反做新功能版本,并生成新提交

git rebase -i HEAD~3                                    #合并revert3个版本的提交

    #修改两个pick为squash (pick表示保留提交、squash指将这个提交合入其他提交)
    #如果有冲突,需要解决冲突 然后执行
    git add .  
    git rebase --continue 
    #如果要放弃rebase,执行
    git rebase --abort  

    #没有冲突的话,会出现commit message界面,wq保存后即可
  1. 创建SSH Key
  • 执行以下命令,然后一路回车,使用默认值即可
  • 登陆GitHub,打开 “Account settings” =》 “SSH Keys” 页面
  • 点击 “Add SSH Key”,在Key文本框里粘贴此步生成的 id_rsa.pub 文件的内容
  • 之后采用git协议访问仓库,可不需要输入密码
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"
  1. 打开原Windows下硬盘中工程,Git中所有文件均提示CRLF换行符变更解决方案
git config --global core.autocrlf input                    #true:提交时转换为LF,检出时转换为CRLF,input:提交时转换为LF,检出时不转换, false:提交检出均不转换
git config --global core.safecrlf true                    #true拒绝提交包含混合换行符的文件,false允许提交包含混合换行符的文件,warn提交包含混合换行符的文件时给出警告
  1. 合并三个提交为一个提交
git rebase -i HEAD~3
修改需要合并的commit的行,将commit前的pick改为squash或者缩写s即可
保存,修改提交信息
  1. 修改远程倒数第三个提交中的某个文件,删除敏感信息
#确保所有改动都提交后
git rebase -i HEAD~5    # 启动交互式变基,停在指定提交,弹出编辑器把要改的那一行的 pick 改成 edit
git add filename        # 修改
git commit --amend --no-edit   # 覆盖提交 --no-edit:保持原来的提交信息不变,只改文件内容。
git rebase --continue   # 把后面的提交 “接回来”

三、其他

  1. Git数据存储的原理浅析 - 个人文章 - SegmentFault 思否 https://segmentfault.com/a/1190000016320008?utm_source=tag-newest

  2. Linux源码克隆错误:Clone succeeded, but checkout failed. drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c

git config core.protectNTFS false
git reset --hard HEAD
  1. gitmoji表情使用规范:https://gitmoji.dev/

  2. 新建的远程仓库操作命令行指令:Command line instructions

  • Git global setup
git config --global user.name "root"
git config --global user.email "root@mail.com"
  • Create a new repository
git clone git@github.com:username/repository.git
cd dify
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
  • Existing folder
cd existing_folder
git init
git remote add origin git@github.com:username/repository.git
git add .
git commit -m "Initial commit"
git push -u origin master
  • Existing Git repository
cd existing_repo
git remote rename origin old-origin
git remote add origin git@github.com:username/repository.git
git push -u origin --all
git push -u origin --tags
  1. svn操作
git svn clone https://svn.example.com/svn/repo --username test
git svn clone -T trunk -b branches -t tags https://svn.example.com/svn/repo
git svn log         # 查看 SVN 日志
git checkout -b hotfix remotes/branches/hotfix   # 处理分支
git add -A .
git commit -m "概要设计书"
git svn fetch       # 获取远程分支更新
git svn rebase      # 更新
git svn dcommit     # 推送
  1. 批量修改提交用户及邮箱
git filter-branch --env-filter '
NEW_NAME="username"
NEW_EMAIL="username@mail.com"

# ========== 在这里维护所有旧邮箱列表 ==========
OLD_EMAILS=(
"root@mail.com"
)
# ========== 在这里维护所有旧用户名列表 ==========
OLD_NAMES=(
"root"
)

# 判断函数:检查入参是否在数组内
in_array() {
    local val="$1"
    shift
    for item in "$@"; do
        if [ "$val" = "$item" ]; then
            return 0
        fi
    done
    return 1
}

# 处理 committer
if in_array "$GIT_COMMITTER_EMAIL" "${OLD_EMAILS[@]}" || in_array "$GIT_COMMITTER_NAME" "${OLD_NAMES[@]}"
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi

# 处理 author
if in_array "$GIT_AUTHOR_EMAIL" "${OLD_EMAILS[@]}" || in_array "$GIT_AUTHOR_NAME" "${OLD_NAMES[@]}"
then
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi

' --tag-name-filter cat -- --branches --tags
  1. 将主仓库根目录下 static 目录剥离历史,转为独立Git子模块,并保留完整提交历史 。

注意:这套脚本适用前提:

  1. static 在仓库根目录
  2. static目录的文件已经提交进主仓库git历史(不是仅暂存未commit)
  3. 目标远程仓库 hugo-static 是空仓库(无README、无初始commit)
# 进入主仓库根目录
# 1. 从主仓库历史剥离 static 目录,新建临时分支 static,保留全部历史提交
git subtree split --prefix=static -b static

# 2. 主仓库:解除 static 的索引跟踪,本地磁盘文件保留不动
git rm -r --cached static

# 3. 进入 static 目录,初始化为新Git仓库(main分支)
cd static
git init -b main

# 4. 临时添加上层主仓库作为remote,用来拉取刚才split出来的历史
git remote add split ..

# 5. 拉取主仓库中临时分支 static(split剥离出来的历史)
git fetch split static

# 6. 将当前static仓库main分支强制重置到split出来的提交,一次性载入历史+文件
git reset --hard FETCH_HEAD  # !会覆盖:替换为split导出的版本会覆盖static目录工作区文件

# 7. 删除临时remote,不再依赖主仓库对象库
git remote remove split

# 8. 绑定static独立远程仓库,推送到远端
git remote add origin git@github.com:username/hugo-static.git
git push -u origin main

# 9. 返回主仓库根目录
cd ..

# 10. 在主仓库挂载static为git子模块(使用远程仓库地址)
git submodule add git@github.com:username/hugo-static.git static

# 11. 吸收内嵌的.git目录,修复子模块目录嵌套git问题(submodule add不会自动做)
git submodule absorbgitdirs

# 12. 提交主仓库变更:.gitmodules配置 + static子模块commit指针
git add .gitmodules static
git commit -m "refactor: convert static folder to submodule, retain full history"

# 13. 删除主仓库内split产生的临时载体分支,清理垃圾
git branch -D static

# 📌 后续日常维护命令(配套保存,写完上面脚本顺带存这个)

# ========== 日常更新静态资源流程 ==========
# 1. 进入子模块目录修改文件
cd static
# 2. 在子模块内提交改动
git add .
git commit -m "feat: add new demo image"
# 3. 推送到static独立远程仓库【必须push,否则别人拉主仓库会找不到commit】
git push origin main

# 4. 返回主仓库,更新主仓库记录的子模块commit指针
cd ..
git add static
git commit -m "update static submodule reference"
git push origin main


# 新机器克隆整套项目完整命令:
git clone 你的博客主仓库地址 blog
cd blog
git submodule update --init --recursive
← 返回技术