# Git使用

# 0、创建版本库

git init 可以初始化本地仓库。

git clone <repository_url> 从远程克隆仓库到本地,分支是远程的默认分支。先创建远程库,直接克隆到本地,就不需要在本地再新建了。

如果想克隆指定分支,可以使用 git clone -b <branch_name> <repository_url>

工作区:当前工作的文件夹(working directory)

# 0.5、工作区、暂存区 Stage

工作区就是我们的文件夹目录。.git 文件夹可以看做是我们的版本库。版本库由暂存区和分支等组成。

git add 把文件添加进去,实际上就是把文件修改添加到暂存区;

git commit 提交更改,实际上就是把暂存区的所有内容提交到当前分支。

# 1、配置用户

# 1.1 配置全局用户

# 配置全局用户
git config --global user.name "xdyuan"
git config --global user.email "xdyuan@gmail.com"
# 查看配置项
git config -l

# 1.2 配置本地用户

如果不想配置全局用户,只想配置某一个 repo 下的。进到这个 repo 的目录下,然后配置当前 repo 的用户。

git config user.name "xdyuan"
git config user.email "xdyuan@gmail.com"

# 2、git add 添加文件到版本库

git add 添加新的文件到暂存区

git add -u 仅添加已经被 add 的文件(即 tracked file),不会提交新建文件(untracked file)

git add . 添加所有的文件到版本库

git status 查看版本库的状态,简写 git s

git diff 查看文件修改前后的区别

git diff HEAD -- README.md 查看某个文件的区别

# 2.5、修改和撤销 restore

# 场景1:还原单个文件到仓库最新版本(未 add)

本地修改了某个文件,未执行 git add,想要还原为仓库最新版本:

git restore 文件名

示例:

git restore index.js

# 场景2:放弃所有文件的本地修改(未 add)

本地多处改动,全部作废,一键还原干净工作区:

git restore .

# 场景3:取消暂存(git add 撤回,保留本地修改)

误执行 git add,想把文件从暂存区撤回工作区,保留代码修改,仅取消待提交状态:

# 撤回单个文件
git restore --staged 文件名

# 撤回所有文件
git restore --staged .

# 场景4:还原文件到指定提交的状态

如果想将文件恢复到特定提交的状态,可以使用:

git restore --source=commit_id file

这个命令在需要查看历史状态或将文件还原到历史版本时非常有用。

# 场景5:交互式还原

以下命令允许你以交互方式选择要还原或保留的更改:

git restore -i

执行这个命令会打开一个交互式界面,让你选择如何处理每个更改。

git restore 的目标是提供一种更直观、易于理解的方式来管理文件的状态。它的引入使得 Git 用户能够更容易地处理不同阶段的更改,从而提高了工作流的效率。需要注意的是,git restore 是 Git 2.23 版本引入的一个命令,如果你使用的是较早版本的 Git,可能无法使用 git restore 命令,但你仍然可以使用 git checkout 等命令来进行类似的操作。

与其他命令的对比:

git restoregit reset 的区别在于,git restore 更多地用于操作工作区和暂存区的内容,而 git reset 通常用于重置提交点。git restoregit checkout 的区别在于,git restore 提供了更细粒度的控制,允许你只操作工作区或暂存区,而 git checkout 通常用于切换分支或还原文件内容。

# 3、设定默认远程 push 分支

设定本地分支跟踪的上游分支:

git branch --set-upstream-to=origin/dev

git branch -u origin/dev 和上面是一个意思。

现在随便修改一下工程文件的内容,然后 git commitgit push,之后就可以直接提交到远程的 dev 分支中,而不会是 master。

git branch --unset-upstream master 撤销本地与远程分支的映射关系。

设定默认 push 分支:

git push -u origin master(完整写法 git push --set-upstream origin master),第一次 push 时使用 -u 参数关联本地 master 分支和远程 master 分支,后续可以简化命令。

git push origin dev 把本地的 dev 分支推送到远程。

如果远程已经存在 dev 分支,但是本地还没有,可以使用 git checkout -b dev origin/dev,基于远程分支 dev 创建本地分支 dev。后续拉取代码就可以使用 git pull origin dev,推送就用 git push origin dev

# 4、编辑 commit 提交内容

git commit -m "message" 提交修改。

git commit --amend 编辑最近一次的提交日志。

编辑某一次的 commit 提交日志,需要使用 rebase 命令。

# 1、比如想修改最近三次提交中的某一次提交信息
git rebase -i HEAD~3

# 2、此时会给你一个交互的信息, 你可以按a或者i来编辑

pick 367d676 2nd submit,new submit
pick 3a0fb46 3rd submit by xdyuan
pick 0021c7d 第四次提交-变基来修改commit msg

# Rebase 3f9fcd7..0021c7d onto 3f9fcd7 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# x, exec <command> = run command (the rest of the line) using shell

# 如果你想修改 3a0fb46 这一次提交的信息,这里我们用 r 就行,没必要用 e。
# 把 pick 3a0fb46 3rd submit by xdyuan 改成 r 3a0fb46 3rd submit by xdyuan
# 然后按 esc 之后再输入 :wq。然后回车编辑你的新信息之后,继续按 esc 之后再输入 :wq 回车,就完成了

# 4.5、reset 回退

git reset --hard HEAD^ 回退到上一个版本,HEAD^^ 表示前 2 个版本,前 100 个版本可以写成 HEAD~100。这是强制回退,文件都会被修改。

git reset --soft HEAD~1 回退到上一个版本,会删除 commit 记录,相比 hard 不会重置文件内容,可以修改后再次提交。

git reset --hard commit_id 可以回到对应提交 id 的版本。

--mixed 会回退到上个版本已添加但未提交的状态。而 --soft 会回退到上个版本的未提交状态。

Reset 之后往往本地的版本会落后远端的版本,这时候如果需要推送就得借助 git push -f,也就是 force push 强制推送。

reset 之后 git log 可能就看不到日志了,需要使用 git reflog。此时可以找到被 reset 掉的 reseted_commit_id。使用这个 id 再次使用 reset 还原 git reset --hard reseted_commit_id

# 4.6、丢弃文件

# 一、只丢弃工作区未 add 的改动(已 git add 的暂存区保留)

git checkout -- .

只撤销单个文件用 git checkout -- <file>(旧写法;新版推荐 git restore,见 2.5)。

# 二、清空暂存区 + 丢弃所有本地修改(最常用,全部复原)

  1. 先撤销所有 add 的文件(清空暂存)

    git reset HEAD .
    

    也可只清空单个文件:git reset HEAD <file>

  2. 再丢弃工作区改动

    git checkout -- .
    

# 三、同时删除新增未跟踪文件(新建没 add 的文件也删掉)

git clean -fd

-f:强制删除文件

-d:同时删除未跟踪文件夹

# 5、关于日志

git log 查看日期

git log --pretty=oneline 查看格式化的单行日志

git log --pretty=format:%s 查看格式化的 commit 日志

git log --graph --pretty=oneline --abbrev-commit 查看分支合并情况

git reflog 查看命令历史,记录了所有的命令

# 5.1 查看某个文件夹的提交历史

git log -- /folder

# 5.2 在指定分支内,按提交备注(message)筛选 commit

# 只在 `release` 这条分支上,查找提交说明包含 `bugfix` 的提交
git log dev --grep="bugfix"

# 只输出 hash + 提交标题(简洁列表)
git log dev --oneline --grep="订单"

# 正则多关键词匹配(多个条件)
git log dev --grep="bug\|fix"

# 6、checkout

本章为旧版(Git 2.23 之前)的撤销命令,新命令推荐使用 git restore,见 2.5。

git checkout -- <file> 撤销修改,回到上一次 add 或者 commit 时的状态。修改了文件但是还没有提交,这时候不想要了,丢弃的话可以使用这个(整目录写法见 4.6)。

git reset HEAD <file> 撤销暂存区的修改,回到 add 之前。文件内容不会发生变化(与 4.6 的 git reset HEAD . 互补)。

# 7、rm 删除 和 恢复

git rm test.txt 删除文件,之后可以直接 commit 提交删除操作。

恢复删除的文件:不小心从本地删除文件,git checkout -- file_name 可以重新恢复。

# 8、远程仓库

# 8.1 关联远程仓库

现有本地库,再创建远程库,此时创建的远程库最好是空的。

git remote add origin <remote_repo_url> 添加远程库。

git remote remove origin 取消关联远程仓库。

git remote -v 查看自己的权限。

git push -u origin master 推送本地仓库到远程库。

把本地库的内容推送到远程,用 git push 命令,实际上是把当前分支 master 推送到远程。

由于远程库是空的,我们第一次推送 master 分支时,加上了 -u 参数,Git 不但会把本地的 master 分支内容推送到远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来,在以后的推送或者拉取时就可以简化命令。

以后做了修改就可以 git push origin master 把本地 master 分支的最新修改推送到 origin 远程仓库。

# 9、分支相关

git branch -a 查看所有分支

git branch dev 创建 dev 分支

git checkout dev 切换为 dev 分支

git branch 查看当前分支和其余分支

git branch -d dev 删除 dev 分支

git push origin --delete [branch_name] 删除远端分支

git branch -D [branch-name]:branch-name 分支如果还没有被合并,此时删除将丢失掉修改,如果要强行删除,需要使用大写的 -D 参数。

# 9.1 切换分支

以前的方式,切换已存在的分支 git checkout <branch-name>

新建分支并切换 git checkout -b <new-branch-name>

新的方式,switch 命令:

创建并切换到新的 dev 分支,可以使用:git switch -c dev

切换到已存在的 dev 分支,git switch dev

# 9.2 给分支添加备注(git-br)

npm i -g git-br

git config branch.分支名称.description 杭州安全通开发分支

git br 查看分支描述

# 9.3 重命名分支

git branch -m main

# 10、Stash

git stash 存储工作现场,等以后恢复现场后继续工作:这个主要用于当有临时 bug 需要修复,但是当前工作未完成,需要先修 bug,但是不提交。

git stash list 存储列表

git stash pop 恢复工作现场

git stash apply stash@{0} 应用某个 stash,但是不删除

git stash drop stash@{0} 删除 stash

git stash save -m "此次stash的目的"

如果想 stash 还没有跟踪的文件

git stash push -u -m "msg"
  • ✅ 保留文件为 未跟踪状态(untracked)
  • ✅ 弹出(pop)后文件仍为未跟踪
  • ✅ 不会污染 Git 索引

只 stash 某个文件

git stash push src/.../xxx.js

查看某个 stash 内容

git stash show -p stash@{0}

# 11、tag 标签

git tag <tagname> 创建一个标签,默认是当前最新的 commit;git tag <tagname> <commit-id> 也可以指定一个以前的 commit 打 tag。

git tag -a <tagname> -m "desc" 可以给这个标签加说明文字。

git tag 查看所有的标签。

git show <tagname> 可以查看这个标签的详情。

git tag -d <tagname> 删除标签。

git push origin <tagname> 推送标签到远程。

git push origin --tags 推送所有的标签到远程。

# 12、关于合并

# 12.1 只合并文件的改动,不合并提交 commit 记录

注意下面只是简单的文件拷贝,不会合并。

# 先切换到想要合并到的分支,可以用 git checkout target-branch
git checkout source-branch -- .

这将会把 source-branch 分支上的所有变更(但不包括 commit)应用到当前的 target-branch 分支上,需要创建一个新的 commit 来记录这次变更。

如果只想把某个文件拷贝过来:

git checkout dev4 src/1.js

如果想把某个文件夹下的文件变动拷贝过来:

git checkout dev4 src/*

# 12.2 git merge fast-forward 快进合并

git merge dev

合并指定分支(dev)到当前分支,使用 fast forward 模式,也叫做快进合并。

“快进合并是指在合并操作中,如果当前分支的历史完全包含在目标分支的历史中,Git 可以直接将当前分支指向目标分支的最新提交,而无需生成额外的合并提交。换句话说,Git 在这种情况下无需创建新提交来表示‘合并’操作。”

简单来说,快进合并意味着目标分支已经是当前分支的“延续”。

示例场景

假如我们有一个 repo 的 main 分支,最初历史如下:

A -- B -- C(main)

然后我们新建一个名为 feature 的分支,并在这个分支上进行了两次提交:

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

如果在 main 分支没有额外的提交,现在你想要将 feature 分支合并回 main 分支,在这种情况下,main 分支的提交历史完全是 feature 分支提交历史的子集。因此我们可以使用快进合并,只需要将 main 分支的指针指向 feature:

A -- B -- C -- D -- E (main, feature)

使用如下的命令:

git checkout main
git merge feature

这种情况不会产生额外的合并提交,只移动 main 分支的指针到 feature 最新提交 E。合并后的历史是线性的,简化了项目的历史记录。

如果不想快进合并,仍然想保留分支历史,可以使用 --no-ff

# 12.3 非快进合并

git merge --no-ff -m "merge with no-ff" dev 不适用 fast forward 模式合并分支,此种方法会保留分支记录。

非快进合并示例:

假如我们有一个 repo 的 main 分支,最初历史如下:

# main
A -- B -- C(main)

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

如果 main 分支也进行了新的提交 F:

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

在这种情况下,git 无法进行快进合并,会创建一个新的合并提交记录:

A -- B -- C -- F -- M (main)
           \      /
            D -- E (feature)

# 12.4 refusing to merge unrelated histories

报错 refusing to merge unrelated histories 出现在两个仓库没有共同提交历史时,可以使用:

git pull origin master --allow-unrelated-histories

# 13、cherry-pick 遴选

# 13.1 只合并某一个分支的某一次 commit 到当前分支

  1. 使用 git cherry-pick 命令来选择并应用该 commit: 一旦你有了 commit 的哈希值,就可以使用 git cherry-pick 命令来应用它。例如,如果你的 commit 哈希值是 abc1234,你可以运行:

    git cherry-pick abc1234
    

    这条命令会将指定的 commit 应用到当前分支上。

  2. 解决冲突(如果有的话): 如果合并过程中出现了冲突,Git 会暂停 cherry-pick 操作,并让你解决冲突。你需要手动编辑冲突的文件,解决冲突后,使用以下命令继续 cherry-pick 操作:

    git add <resolved-file>
    git cherry-pick --continue
    

    如果你决定放弃这次 cherry-pick 操作,可以使用:

    git cherry-pick --abort
    

# 13.2 把目标提交所有改动应用到你的工作区与暂存区,不自动生成新 commit,HEAD 不移动

# 简写
git cherry-pick -n <commitHash>
# 完整写法
git cherry-pick --no-commit <commitHash>

遇到冲突怎么处理

  1. 执行 -n 后出现冲突,文件带冲突标记
  2. 手动解决冲突,git add 冲突文件
  3. 不要执行 git cherry-pick --continue(continue 会自动提交)
  4. 全部解决完直接 git commit 即可

# 14、git show

git show 是查看 Git 对象详情的命令,默认查看单个提交的完整变更,也能看标签、分支、文件历史、某次提交里单个文件改动。

核心能力:

  1. 查看某次 commit 的作者、时间、提交备注、全部代码 diff
  2. 查看某个 tag 对应的提交内容
  3. 查看某一版本下单个文件完整内容 / 改动
  4. 只导出提交补丁,配合 apply 复制代码改动

实用场景:配合 git apply 复制代码

# 方式1:直接应用到工作区(不暂存)
git show a72f9d | git apply

# 方式2:应用并加入暂存区(等价 cherry-pick -n)
git show a72f9d | git apply --index

# 14.1 只列出改动的文件名(最简)

# 仅文件名称
git show --name-only abc123

# 文件 + 修改状态 A新增 / M修改 / D删除 / R重命名
git show --name-status abc123

# 14.2 显示修改行数统计(文件 + 增删行数)

git show --stat abc123
# 紧凑模式
git show --shortstat abc123

# 15、抓取和拉取

git 抓取(fetch)和 git 拉取(pull)的主要区别在于它们对远程仓库数据的处理方式和适用场景不同。

# 15.1 行为差异

  • git fetch:从远程仓库获取最新的提交和分支信息,但不会自动将这些更改合并到当前分支。远程分支(如 origin/main)会更新,但本地分支(如 main)保持不变。
  • git pull:相当于 git fetch 和 git merge 的组合,从远程仓库获取最新的提交和分支信息,并立即将这些更改合并到当前分支。这意味着本地分支会自动更新为与远程分支同步的状态。

# 15.2 适用场景

  • git fetch:适用于想要先了解远程仓库的最新状态,再决定如何处理更新的情况。对更改合并有更精确的控制,适合在多人协作项目中使用。
  • git pull:适用于确定需要立即将远程更改同步到本地分支的情况。对合并行为无需过多控制,适合在单人项目中使用更为方便。

# 15.3 具体操作示例

  • git fetch:例如,git fetch origin main 会从远程仓库获取最新的提交和分支信息,但不会自动合并到当前分支。
  • git pull:例如,git pull origin main 会从远程仓库获取最新的提交和分支信息,并立即将这些更改合并到当前分支。

# 15.4 pull 错分支

有时你在 dev 分支不小心 git pull origin master。此时你并不需要 master 的代码,你可以:

git merge --abort

# 16、git revert

git revert 用于反做某一个版本,比如 commit 了三次,但是第二次不想要了,但是保留第三次的提交,就需要用到 revert

git revert -n commit_id 反做这个 id 的 commit。可能会出现冲突,需要手动解决,然后重新 commit 一次即可。注意此时的 commit message 最好写成如下格式:

Revert "feat(txt): add txt"

This reverts commit 6788a3c72b6bae5a9780503ea69681da18f44c3e.

# 17、git rebase

Rebase 可以对某一段线性提交历史进行编辑、删除、复制、粘贴,合理使用 rebase 可以使得我们的提交历史干净简洁。

1、合并多个 commit 为一个完整的 commit

# 区间记号(前开后闭),此处写法待校对
git rebase -i (startpoint endpoint]

# 2 表示要合并的数量
git rebase -i HEAD~2

2、将某一段 commit 粘贴到另一个分支上

# 区间记号(前开后闭),此处写法待校对
git rebase -i (startpoint endpoint] --onto [branchName]

--onto 的意思是要将该指定的提交复制到哪个分支上,此时的 HEAD 是有问题的,一般需要:

git checkout branchName
git reset --hard last_commit

# 18、Fork 之后如何拉取代码提交 PR

此种情况适用于本地 clone 的是 fork 后的仓库,然后需要拉取原仓库,同时提交自己的代码到原仓库,可以提交 PR,PR 可以邀请人来审核之后 merge。

  1. 本地添加原仓库的地址

    git remote add upstream <原仓库git地址>
    
  2. 获取原仓库指定分支的更新

    git fetch upstream main
    
  3. 合并原仓库的指定分支代码到本地的分支

    git merge upstream/main
    
  4. 有冲突的话需要合并

  5. 修改代码合并之后提交到本地仓库

    git add .
    git commit -m "some change"
    
  6. 推送提交到自己 fork 的仓库

    git push origin dev
    
  7. 这时候可以到 gitlab 或者 github 提交 PR。等待审核人合并 PR 即可。

上次更新: 9/14/2026, 3:34:29 AM