Git使用与配置
Git配置
/etc/gitconfig文件:系统中对所有用户都普遍适用的配置。若使用git config时用--system选项,读写的就是这个文件。~/.gitconfig文件:用户目录下的配置文件只适用于该用户。若使用git config时用--global选项,读写的就是这个文件。- 当前项目的 Git 目录中的配置文件(也就是工作目录中的
.git/config文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config里的配置会覆盖/etc/gitconfig中的同名变量。
配置用户信息
1 | $ git config --global user.name "you_name" |
如果用了 –global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。
如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 –global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
编辑git配置文件 git config
1 | $ git config -e # 针对当前仓库 |

1 | $ git config -e --global # 针对系统上所有仓库 |

查看配置信息 git config --list
1 | $ git config --list |

查询指定某个信息(查看用户名称)
1 $ git config user.name
Git对仓库进行克隆(下载)git clone
克隆仓库的命令格式为:
1 | $ git clone <repo> |
如果我们需要克隆到指定的目录,可以使用以下命令格式:
1 | $ git clone <repo> <directory> |
参数说明:
- **repo:**Git 仓库。
- **directory:**本地目录。
Git创建仓库(初始化) git init
当前目录下创建
1 | $ git init |
在当前目录下z创建hongpeng_code文件夹并在其中创建 .git
1 | $ git init zhongpeng_code |
Git将文件添加到暂存区 git add
多文件添加
1 | $ git add [file1] [file2] |
添加目录
1 | $ git add [dir] |
添加当前目录下的所有文件
1 | $ git add . |
Git查看上次提交之后是否对文件进行再次修改 git status
1 | $ git status |
使用 -s 参数来获得简短的输出结果
1 | $ git status -s |
AM 状态的意思是这个文件在我们将它添加到缓存之后又有改动。
Git比较文件的不同(暂存取与工作区的差异) git diff
git diff 有两个主要的应用场景。
- 尚未缓存的改动:git diff
- 查看已缓存的改动: git diff –cached
- 查看已缓存的与未缓存的所有改动:git diff HEAD
- 显示摘要而非整个 diff:git diff –stat
显示暂存区和工作区的差异:
1 | $ git diff [file] |
显示暂存区和上一次提交(commit)的差异:
1 | $ git diff --cached [file] |
显示两次提交之间的差异:
1 | $ git diff [first-branch]...[second-branch] |
Git将暂存区内容添加到本地仓库 git commit
-m添加注释
1 | $ git commit -m "我的注释" |
提交暂存区的指定文件到仓库 git commit [file1] [file2] ... -m [message]
1 | $ git commit [file1] [file2] ... -m [message] |
在不add的情况下将文件添加到仓库 git commit -a
-a 参数设置修改文件后不需要执行 git add 命令,直接来提交
1 | $ git commit -a |
Git上次添加到本地仓库 进行修改commit信息 git commit --amend
1 | # 修改最近提交的 commit 信息 |
修改历史提交 commit 的信息
操作步骤:
git rebase -i列出 commit 列表找到需要修改的 commit 记录,把
pick修改为edit或e,:wq保存退出修改 commit 的具体信息
git commit --amend,保存并继续下一条git rebase --continue,直到全部完成中间也可跳过或退出
git rebase (--skip | --abort)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 # 列出 rebase 的 commit 列表,不包含 <commit id>
$ git rebase -i <commit id>
# 最近 3 条
$ git rebase -i HEAD~3
# 本地仓库没 push 到远程仓库的 commit 信息
$ git rebase -i
# vi 下,找到需要修改的 commit 记录,```pick``` 修改为 ```edit``` 或 ```e```,```:wq``` 保存退出
# 重复执行如下命令直到完成
$ git commit --amend --message="modify message by test" --author="YuKiFuHaNe <915228208@qq.com>"
$ git rebase --continue
# 中间也可跳过或退出 rebase 模式
$ git rebase --skip
$ git rebase --abort
Git回退版本 git reset
1 | $ git reset [--soft | --mixed | --hard] [HEAD] |
–soft 参数用于回退到某个版本:
–mixed 为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变。
–hard 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交:
**注意:**谨慎使用 –-hard 参数,它会删除回退点之前的所有信息。
指定回退版本
1 | $ git reset HEAD^ # 回退所有内容到上一个版本 |
指定文件回退
1 | $ git reset HEAD^ my.py # 回退my.py文件的版本到上一个版本 |
撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交
1 | git reset --hard HEAD |
HEAD 说明:
HEAD 表示当前版本
HEAD^ 上一个版本
HEAD^^ 上上一个版本
HEAD^^^ 上上上一个版本
以此类推…
可以使用 ~数字表示
- HEAD~0 表示当前版本
- HEAD~1 上一个版本
- HEAD^2 上上一个版本
- HEAD^3 上上上一个版本
- 以此类推…
Git删除文件 git rm
将文件从本地和暂存区删除 git rm <file> 谨慎使用
1 | $ git rm <file> |
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f
1 $ git rm -f <file>
只删除暂存区的文件 git rm --cached <file>
1 | $ git rm --cached <file> |
Git移动、重命名文件、目录或软连接 git mv
1 | $ git mv <file> <newfile> |
如果新文件名已经存在,但还是要重命名它,可以使用 -f 参数:
1 | $ git mv -f <file> <newfile> |
Git查看提交历史 git log
全部提交记录 git log
1 | $ git log |
--oneline查看记录的简洁版本 git log --oneline
1 | $ git log --oneline |
--graph查看历史中什么时候出现了分支、合并 git log --graph
1 | $ git log --graph |
--author查看指定用户的提交日志 git log --author
查看zhongpeng用户已简洁版本后5行
1 | $ git log --author=zhongpeng --oneline -5 |
Git查看操作(删除移除等)日志 git reflog
1 | $ git reflog |

该日志仅保留在本地
1
2
3
4
5
6
7 git reflog [show] [<log-options>] [<ref>]
git reflog expire [--expire=<time>] [--expire-unreachable=<time>]
[--rewrite] [--updateref] [--stale-fix]
[--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>…]
git reflog delete [--rewrite] [--updateref]
[--dry-run | -n] [--verbose] <ref>@{<specifier>}…
git reflog exists <ref>
查看指定范围的日志 --since ~ --until或--before ~ --after
Git 项目中三周前且在四月十八日之后的所有提交
1 | $ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges |
merges 选项以隐藏合并提交
Git以列表形式查看修改、提交历史 git blame <file>
查看指定文件的修改记录
1 | $ git blame <file> |
Git远程仓库操作 git remote
显示所有远程仓库 git remote -v
1 | $ git remote -v |
显示某个远程仓库信息 git remote show
1 | $ git remote show 仓库地址 |
添加远程版本库 git remote add
1 | $ git remote add <shortname> <url> |
shortname:本地的版本库
1
2
3 # 提交到 Github
$ git remote add origin git@github.com*****/*****-test.git
$ git push -u origin master
删除远程仓库 git remote rm
1 | $ git remote rm <name> |
修改远程仓库名称 git remote rename
1 | $ git remote rename <old_name> <new_name> |
Git远程获取代码库 git fetch
1 | $ git fetch [alias] # 将远程代码库同步到本地 |
1 | $ git merge [alias]/[branch] # 从远端仓库提取数据并尝试合并到当前分支 |
1
2
3
4
5
6
7
8
9
10 方法一
git fetch origin master #从远程的origin仓库的master分支下载代码到本地的origin maste
git log -p master.. origin/master #比较本地的仓库和远程参考的区别
git merge origin/master #把远程下载下来的代码合并到本地仓库,远程的和本地的合并
方法二
git fetch origin master:temp #从远程的origin仓库的master分支下载到本地并新建一个分支temp
git diff temp #比较master分支和temp分支的不同
git merge temp #合并temp分支到master分支
git branch -d temp #删除tempalias:别名
下载远程代码并合并 git pull
git fetch 和 git merge FETCH_HEAD 的简写
1 | $ git pull |
上传远程代码并合并 git push
1 | $ git push <远程主机名> <本地分支名>:<远程分支名>如果本地分支名与远程分支名相同,则可以省略冒号: |
上传远程代码并合并 git push
git push 命令用于从将本地的分支版本上传到远程并合并。
命令格式如下:
1 | $ git push <远程主机名> <本地分支名>:<远程分支名> |
如果本地分支名与远程分支名相同,则可以省略冒号:
1 | $ git push <远程主机名> <本地分支名> |
以下命令将本地的 master 分支推送到 origin 主机的 master 分支。
1 $ git push origin master相等于:
1 $ git push origin master:master如果本地版本与远程版本有差异,但又要强制推送可以使用 –force 参数:
1 $ git push --force origin master删除主机的分支可以使用 –delete 参数,以下命令表示删除 origin 主机的 master 分支:
1 $ git push origin --delete master
子模块(submodule) git submodule add <url> <repo_name>
初始化子模块 git submodule update
1 | git submodule update --init --recursive |
更新子模块 git submodule update
1 | git submodule update |
更新子模块为远程项目的最新版本 git submodule update --remote
1 | git submodule update --remote |
下载主仓库的所有项目内容 git clone --recursive
1 | git clone --recursive <project url> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 ## 删除子模块
# 删除子模块文件夹
$ git rm --cached <repo_name>
# 删除 .gitmodules 文件中相关子模块的信息类似于
[submodule "repo_name"]
path = repo_name
url = https://github.com/author/GWToolkit.git
# 删除 .git/config 中相关子模块信息 ,如果对子模块有自己的更改或提交就会有这个
[submodule "repo_name"]
url = https://github.com/author/repo_name.git
active = true
# 删除 .git 文件夹中的相关子模块文件
$ rm -rf .git/modules/GWToolkit
子树(subtree) git subtree 将一个项目的子目录作为独立的Git仓库处理
添加子树 git subtree add
1 | $ git subtree add --prefix=<subtree-directory> <remote-url> <branch> --squash |
拉取子树的更新 git subtree pull
1 | $ git subtree pull --prefix=<subtree-directory> <remote-url> <branch> --squash |
推送子树的更改 git subtree push
1 | $ git subtree push --prefix=<subtree-directory> <remote-url> <branch> --squash |
分割子树 git subtree split
1 | $ git subtree split --prefix=<subtree-directory> --branch=<new-branch> |
典型使用场景
git subtree split是git subtree命令的一个子命令,用于将一个子树(子目录)从当前仓库中分离出来,创建一个新的分支,其中只包含子树的历史记录。这在将子树转移到一个独立的仓库或将其与其他仓库合并时非常有用。以下是
git subtree split的详细用法:
1 subtree split --prefix=<subtree-directory> --branch=<new-branch> [--annotate=<annotation>] [--rejoin] [--onto=<commit>]
<subtree-directory>:要分离的子树目录。<new-branch>:新创建的分支名称,其中包含子树的历史记录。--annotate=<annotation>(可选):为分离的提交添加注释。这有助于在将来识别子树的来源。--rejoin(可选):在分离子树后,将其重新连接到主仓库。这样,您可以继续在主仓库中跟踪子树的更改。--onto=<commit>(可选):将子树的历史记录重新定位到指定的提交。这在将子树合并到另一个仓库时非常有用。典型的使用场景:
将子树转移到独立仓库:
如果您有一个包含多个项目的仓库,但现在希望将其中一个项目转移到一个独立的仓库,可以使用
git subtree split命令。首先,使用git subtree split创建一个新分支,其中只包含子树的历史记录。然后,将新分支推送到新仓库。将子树与其他仓库合并:
如果您有两个仓库,希望将其中一个仓库的子目录合并到另一个仓库中,可以使用
git subtree split命令。首先,在源仓库中使用git subtree split创建一个新分支,其中只包含子树的历史记录。然后,在目标仓库中使用
git fetch获取新分支,并使用git merge将其合并到目标仓库。从独立仓库中提取子项目:
如果您有一个独立的仓库,其中包含多个子项目,您可以使用
git subtree split将这些子项目分离出来,以便在其他仓库中使用。这样,您可以更轻松地在多个仓库之间共享和重用代码。假设我们有一个名为``main-repo
的Git仓库,其中包含一个名为subproject的子目录。我们希望将subproject`分离出来,并将其转移到一个名为
subproject-repo的新仓库。以下是如何使用git subtree split完成此操作的示例:
- 首先,在
main-repo中使用git subtree split创建一个新分支,其中只包含subproject的历史记录:
1
2 $ cd main-repo
$ git subtree split --prefix=subproject --branch=subproject-branch这将创建一个名为
subproject-branch的新分支,其中包含subproject目录的历史记录。
- 将新分支推送到新仓库:
首先,创建一个名为
subproject-repo的新仓库。然后,在main-repo中将subproject-branch推送到新仓库:
git push <subproject-repo-url> subproject-branch:main其中,
<subproject-repo-url>是新仓库的URL。这将把subproject-branch推送到新仓库的main分支。
- 现在,
subproject-repo已经包含了subproject的历史记录。您可以将其克隆到本地,并开始在新仓库中独立地开发和维护subproject:
1
2 $ git clone <subproject-repo-url>
$ cd subproject-repo这个示例展示了如何使用
git subtree split将一个子目录从现有仓库中分离出来,并将其转移到一个新的独立仓库。3、分离后协同主项目开发
·git subtree split·将子目录分离到新仓库后,您仍然可以在主项目中继续开发子项目。为了在主项目和新仓库之间保持同步,您可以使用
git subtree pull和git subtree push命令。以下是如何在主项目和新仓库之间保持同步的示例:
在主项目中开发子项目:
在主项目的
subproject目录中进行开发和提交更改。将更改推送到新仓库:
当您准备将更改推送到新仓库时,使用
git subtree push命令:
git subtree push --prefix=subproject <subproject-repo-url> main这将把
subproject目录中的更改推送到新仓库的main分支。
- 从新仓库拉取更新:
如果在新仓库中进行了开发,您可以使用
git subtree pull命令将更新拉取到主项目中:
git subtree pull --prefix=subproject <subproject-repo-url> main这将从新仓库的
main分支拉取更新,并将它们合并到主项目的subproject目录中。通过这种方式,您可以在主项目和新仓库之间保持子项目的同步,从而实现协同开发。请注意,为了避免冲突和合并问题,建议在主项目和新仓库之间保持良好的沟通,并确保团队成员了解他们应该在哪个仓库中进行开发。
要避免在主项目中修改subtree子项目后提交中携带了主项目的修改日志:
可以使用
git add命令仅将子项目的更改添加到暂存区,然后进行提交。这样,提交将仅包含子项目的更改,而不会包含主项目的其他更改。以下是如何仅提交子项目更改的示例:
- 在主项目中修改子项目(例如
subproject)。使用git add命令仅将子项目的更改添加到暂存区:
git add subproject/这将仅将subproject目录中的更改添加到暂存区,而不会添加主项目的其他更改。
提交子项目的更改:
git commit -m "Update subproject"这将创建一个新的提交,其中仅包含子项目的更改。通过这种方式,您可以确保提交中仅包含子项目的更改,而不会携带主项目的修改日志。当然,在推送子项目的更改到新仓库时,仍然需要使用git subtree push命令。
Git 仓库浏览器 gitk

GIthub
本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以我们需要配置验证信息:
1 | $ ssh-keygen -t rsa -C "youEail" |


- -t:指定密钥类型,可以使用RSA、DSA、ECDSA、ED25519等。
- -b:指定密钥长度,可以使用1024、2048、3072、4096等,默认为2048。
- -C:添加注释,用于标识该密钥的用途或所属人等。
- -f:指定保存密钥文件的路径和文件名,默认为/.ssh/id_rsa或/.ssh/id_dsa等。
- -N:设置密钥密码,用于保护密钥的安全性。
- -P:修改已有密钥的密码,使用该选项需要先指定已有密钥文件的路径和文件名。
- -q:静默模式,不输出任何信息,常用于批量生成密钥。
- -i:将已有的密钥文件转换为OpenSSH格式。
- -e:将OpenSSH格式的密钥文件转换为其他格式,如PKCS#8格式等。
LFS大文件
GitHub 阻止大小超过 100 MiB 的文件,要跟踪超出此限制的文件,必须使用 Git Large File Storage (Git LFS),下面是Github大文件
| 产品 | 文件大小上限 |
|---|---|
| GitHub Free | 2 GB |
| GitHub Pro | 2 GB |
| GitHub Team | 4 GB |
| GitHub Enterprise Cloud | 5 GB |
Git Large File Storage 的帐户都会获得 1 GiB 的免费存储空间和一个月的免费带宽 1 GiB
什么时候需要 Git LFS
如果你在命令行用
git push添加或更新 $>$ 50MB 的文件,你会收到一个 warning,不过你仍然可以正常push。但如果 $>$ 100MB 的时候就无法push了。如果你是在浏览器要上传文件的话,这个限制更为严重,不能超过 25MB,这是 GitHub 对仓库的限制。Git LFS 就是用于解决这个问题1什么时候不需要用 Git LFS
下面几个场景不需要用
- 文件大小没有超过限制当然就没有必要用了
- 如果是要分发二进制文件(比如
\*.exe)等,此时直接用 GitHub 提供的 release 功能就好了
安装Git Large File Storage
导航到git-lfs.com并单击下载。
1 | ## 验证安装是否成功 |
配置 Git 大文件存储
1 | ## 关联.psd文件 |
删除单个文件
使用
filter-repo命令从仓库的 Git 历史记录中删除文件。 有关使用它们的详细信息,请参阅“从存储库中删除敏感数据”。导航到 .gitattributes 文件。
注意
.gitattributes 文件通常保存在本地存储库中。 在某些情况下,你可能已创建包含所有 Git LFS 关联的全局 .gitattributes 文件。
找到并删除 .gitattributes 文件内关联的 Git LFS 跟踪规则。
保存并退出 .gitattributes 文件。
删除 Git LFS 仓库内的所有文件
(可选)要卸载仓库中的 Git LFS,请运行:
1
git lfs uninstall
对于 1.1.0 以下的 Git LFS 版本,运行:
1
git lfs uninit
追踪的大文件之前不小心加到 Git 仓库里了
此时只是简单使用
git lfs track ...追踪大文件是不够的,因为这个大文件已经存在 Git 仓库的历史记录里,这会导致 Git 仓库无法变小。正确的方法是使用git lfs migrate,将 Git 历史的大文件变成 Git LFS 追踪的对象比如可以用--include=,Git LFS 会自动根据我们指定的模式进行选择。下面的--include="*.txt的意思就是选中 Git 仓库历史的 txt 文件,可以用man git-lfs-migrate查看更多信息
1
2
3
4 git lfs migrate import --include="*.psd"
让远程仓库也改过来
git push --force不再跟踪某些文件
1
2 git lfs untrack "*.psd"
git rm --cached "*.psd"
删除敏感数据
使用 git-filter-repo 从本地存储库的历史记录中清除文件
安装该
git-filter-repo工具的最新版本。您需要一个带有 标志的版本--sensitive-data-removal,即至少 2.47 版本。您可以git-filter-repo手动安装,也可以使用包管理器安装。例如,要使用 HomeBrew 安装该工具,请使用以下brew install命令。1
brew install git-filter-repo
有关更多信息,请参阅存储库中的INSTALL.md
newren/git-filter-repo。将仓库克隆到本地计算机。请参阅克隆仓库。
1
git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
导航到存储库的工作目录。
1
cd YOUR-REPOSITORY
运行
git-filter-repo命令来清理敏感数据。如果要从所有分支/标签/引用中删除特定文件,请运行以下命令,并将其替换
PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA为要删除的文件的 git 路径,而不仅仅是其文件名(例如src/module/phone-numbers.txt):1
git-filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
重要的
如果包含敏感数据的文件曾经存在于任何其他路径(因为它已被移动或重命名),则必须
--path为该文件添加额外的参数,或者再次运行此命令并命名备用路径。如果您想要替换
../passwords.txt存储库历史记录中任何位置找到的任何非二进制文件中列出的所有文本,请运行以下命令:1
git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt
仔细检查您是否已从存储库历史记录中删除了所有您想要删除的内容。
了解此次历史记录重写将对多少拉取请求产生不利影响。您将需要以下信息。
1
grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs
您可以删除
-c以查看哪些拉取请求受到影响:1
2
3
4
5grep '^refs/pull/.*/head$' .git/filter-repo/changed-refs
refs/pull/589/head
refs/pull/602/head
refs/pull/604/head
refs/pull/605/head此输出包含第二和第三个斜杠之间的拉取请求编号。如果受影响的拉取请求数量超出预期,您可以丢弃此克隆,而不会产生任何不良影响,然后重新执行重写或放弃敏感数据删除。一旦您进入下一步,重写将不可逆。
对仓库状态满意后,请强制推送本地更改,以覆盖 GitHub.com 上的仓库。虽然
--force暗示了这一点--mirror,但我们在下方添加了它,以提醒您强制更新所有分支、标签和引用,并丢弃在您清理仓库期间其他人可能对这些引用所做的任何更改。1
git push --force --mirror origin
此命令将无法推送任何以 开头的引用
refs/pull/,因为 GitHub 将这些引用标记为只读。这些推送失败的情况将在下一节中处理。如果任何其他引用推送失败,则可能是您为该分支启用了分支保护,需要暂时关闭它并重新推送。重复此操作,直到更新失败的引用全部以 开头refs/pull/。
从 GitHub 彻底删除数据
使用git-filter-repo删除敏感数据并将更改推送到 GitHub 后,您必须采取更多步骤才能从 GitHub 中完全删除数据。
通过GitHub 支持门户联系我们,并提供以下信息:
- 所涉及的所有者和存储库名称(例如 YOUR-USERNAME/YOUR-REPOSITORY)。
- 上一步中发现的受影响拉取请求数量。支持团队会使用此信息来确认您是否了解受影响的程度。
- 报告的第一个更改的提交
git-filter-repo(在其输出中查找NOTE: First Changed Commit(s)。) - 如果
NOTE: There were LFS Objects Orphaned by this rewrite出现在 git-filter-repo 输出中(紧接着第一次更改提交之后),则说明您有 LFS Objects Orphaned,并将命名文件也上传到票证。
如果您已成功清理除 PR 之外的所有引用,并且没有任何分支引用敏感数据,则支持人员将:
- 取消引用或删除 GitHub 上任何受影响的 PR。
- 在服务器上运行垃圾收集以从存储中删除敏感数据。
- 删除缓存的视图。
- 如果涉及 LFS 对象,请删除和/或清除孤立的 LFS 对象。
重要的
GitHub 支持不会删除非敏感数据,并且仅在我们确定无法通过轮换受影响的凭据来降低风险的情况下才会协助删除敏感数据。
协作者必须对基于您旧的(已污染的)仓库历史记录创建的任何分支进行变基(rebase ),而不是合并。一次合并提交可能会重新引入您刚刚费尽心思清除的部分或全部已污染的历史记录。他们可能还需要采取其他措施;请参阅手册中的“确保其他副本已清理:同事的克隆”
git-filter-repo。
避免将来发生意外提交
防止贡献者意外提交有助于防止敏感信息泄露。更多信息,请参阅防止组织数据泄露的最佳实践。
您可以采取一些措施来避免提交或推送不应共享的内容:
- 如果敏感数据可能存在于不应由 git 跟踪的文件中,请将该文件名添加到
.gitignore(并确保提交并推送该更改,.gitignore以便保护其他开发人员)。 - 避免在代码中硬编码机密。使用环境变量或机密管理服务(例如 Azure Key Vault、AWS Secrets Manager 或 HashiCorp Vault)在运行时管理和注入机密。
- 创建一个预提交钩子,在提交或推送到任何地方之前检查敏感数据,或者在预提交钩子中使用一些知名工具,例如 git-secrets 或 gitleaks。(请务必要求每位协作者设置您选择的预提交钩子。)
- 使用GitHub Desktop或gitk等可视化程序提交更改。可视化程序通常可以更轻松地查看每次提交时添加、删除和修改的文件。
- 避免在命令行上使用catch-all 命令
git add .和- 而是使用和单独暂存文件。git commit -a``git add filename``git rm filename - 用于
git add --interactive单独审查和暂存每个文件中的更改。 - 用于
git diff --cached检查已暂存待提交的更改。git commit只要您未使用此-a标志,就会生成精确的差异。 - 为您的代码库启用推送保护,以检测并阻止包含硬编码机密的推送提交到您的代码库。更多信息,请参阅关于推送保护。
从存储库中删除敏感数据涉及四个高级步骤:
- 使用 git-filter-repo 在本地重写存储库
- 使用本地重写的历史记录更新 GitHub 上的存储库
- 与同事协调清理其他存在的克隆
- 防止重复并避免未来敏感数据泄露
开启警惕模式(可选)
打开一种称为**警惕模式**的东西,在该模式下我们可以显示所有 git 提交的验证状态。

配置用户签名信息 (Github关于提交签名验证)
GitHub添加签名

SSH签名
1 | ### Navigate to cloned repo root for individual repos ### |
全局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 ### Global signing on all repos ###
### Configure name ###
$ git config --global user.name "Your_User_Name"
### Configure email (same as what was specified in SSH key gen) ###
$ git config --global user.email "your_email@example.com"
### Configure Git to use SSH to sign commits and tags
git config --global gpg.format ssh
### set your SSH signing key in Git, paste the text below, substituting /PATH/TO/.SSH/Sign_KEY.PUB ###
$ git config --global user.signingkey "/PATH/TO/.SSH/Sign_KEY.PUB"
### Enable/Enforce commit signing else you need committing changes in your local branch, add the -S flag to the git commit command `git commit -S -m "YOUR_COMMIT_MESSAGE"`###
$ git config --global commit.gpgsign true

1
2
3
4
5
6
7
8
9
10
11
12
13 $ git log --show-signature -1
error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification
commit ******************************* (HEAD -> main)
No signature
Author: YuKiFuHaNe <915228208@qq.com>
Date: Sat Jun 14 20:16:49 2025 +0800
Update Git.md
- Add SSH GPG sign
- format all bash code blocks
Signed-off-by: YuKiFuHaNe <915228208@qq.com>
显示没有签名不影响,这个是本地认证的,当然你也可以配置好本地就不会出现了通过配置#34387
1
2
3 $ cat /PATH/TO/.SSH/Sign_KEY.PUB > /PATH/TO/.SSH/allowed_signers
# 然后编辑allowed_signers格式是<邮箱> <密钥类型> <公钥>
$ git config --global gpg.ssh.allowedSignersFile " /PATH/TO/.SSH/allowed_signers"
1
2
3
4
5
6
7
8
9
10
11
12 $ git log --show-signature -1
commit ********************************* (HEAD -> main)
Good "git" signature for 915228208@qq.com with ED25519 key SHA256:******************************************************
Author: YuKiFuHaNe <915228208@qq.com>
Date: Sat Jun 14 20:16:49 2025 +0800
Update Git.md
- Add SSH GPG sign
- format all bash code blocks
Signed-off-by: YuKiFuHaNe <915228208@qq.com>
GPG签名
生成新的 GPG 密钥
1 | $ gpg --full-generate-key |
1
2 # 如果使用的不是 2.1.17 或更高版本 `gpg --full-generate-key` 命令无效,使用下面这个
$ gpg --default-new-key-algo rsa4096 --gen-key当系统要求输入您的电子邮件地址时,请确保输入您 GitHub 帐户中已验证的电子邮件地址。为了保护您的电子邮件地址的私密性,请使用 GitHub 提供的
no-reply电子邮件地址。有关更多信息,请参阅验证您的电子邮件地址和设置提交电子邮件地址。
使用此gpg --list-secret-keys --keyid-format=long命令列出您拥有公钥和私钥的 GPG 密钥的长格式。签署提交或标签时需要私钥。本例中,GPG 密钥 ID 为1DBE5B4FC75D6BF2:
1 | $ gpg --list-secret-keys --keyid-format=long |

粘贴以下文本,替换您想要使用的 GPG 密钥 ID。在此示例中,GPG 密钥 ID 为1DBE5B4FC75D6BF2,然后将GPG密钥添加到Github
1 | $ gpg --armor --export 1DBE5B4FC75D6BF2 |

告诉Git你的GPG密钥
如果你之前配置 Git 使用不同的密钥格式来使用 --gpg-sign 进行签名,请取消此配置,以便使用 openpgp 的默认格式。
1 | $ git config --global --unset gpg.format |
使用 gpg --list-secret-keys --keyid-format=long 命令来列出你拥有公钥和私钥的 GPG 密钥的完整形式。私钥是用于签名提交或标签所必需的。GPG密钥ID为1DBE5B4FC75D6BF2然后将ID添加到git中
1 | $ gpg --list-secret-keys --keyid-format=long |

1 | $ git config --global user.signingkey 1DBE5B4FC75D6BF2 |
或者,使用一个子密钥。GPG 子密钥 ID 是
C7BA975838CE5DB9
1 $ git config --global user.signingkey C7BA975838CE5DB9
可选地,要配置 Git 默认对所有提交和标签进行签名,可以输入以下命令
1 | $ git config --global commit.gpgsign true |
签名标签
为标签签名,在 git tag 命令中添加 -s
1 | $ git tag -s MYTAG |
通过运行 git tag -v [tag-name] 验证您的已签名标签
1 | $ git tag -v MYTAG |
签名提交 gpgsign 与 signoff

设置别名git config --global alias.cm 'commit --signoff


特性 --signoff(-s)-S(GPG/SSH 签名)类型 纯文本声明 加密签名(密码学验证) 可见性 提交消息中的文本行 隐藏的二进制签名( git log --show-signature查看)目的 法律/流程合规(如 DCO) 身份认证(防伪造) 验证方式 人工检查或脚本匹配 Signed-off-byGit 自动验证密钥有效性 典型用户 开源贡献者 需要高安全性的项目
git commit --amend --no-edit --signoff(-s)
作用:在提交消息末尾 添加一行
Signed-off-by文本(法律声明)。用途:主要用于开源项目(如 Linux 内核),表明贡献者遵守开发者证书(DCO)。
示例输出
1
2
3 Fix login bug
Signed-off-by: Your Name <your@email.com> # 新增的签名行2.
git commit --amend --no-edit -S
- 作用:用 GPG 或 SSH 密钥对提交进行加密签名(生成数字签名)。
- 用途:验证提交的真实性(防篡改),GitHub/GitLab 会显示 “Verified” 徽章。
- 要求:需提前配置 GPG 或 SSH 签名密钥)。
也可以通过模板配置问题进行配置
1 $ git config --global commit.template ~/.commit-message模板示例文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 # ------------------------ COMMIT MESSAGE TEMPLATE ------------------------
# Lines starting with '#' are comments and will be ignored.
# LINES SHOULD BE NO LONGER THAN THIS:
########################################################################
# <type>[optional scope]: <subject>
#
# [Optional body]
#
# [Optional footer(s)]
#
# -------------------------------------------------------------------------
# **Guidelines:**
# <type>: Short identifier of the change type (e.g., feat, fix, docs, style, refactor, test, chore).
# - **feat**: A new feature
# - **fix**: A bug fix
# - **docs**: Documentation changes
# - **style**: Code style updates (formatting, missing semicolons, etc.)
# - **refactor**: Code changes that neither fix a bug nor add a feature
# - **perf**: Performance improvements
# - **test**: Adding or updating tests
# - **chore**: Changes to the build process or auxiliary tools
# [optional scope]: A noun describing the section of the code affected (e.g., parser, API, backend).
# <subject>: A brief summary of the changes in present tense (not capitalized and no period at the end).
# - Use the imperative mood ("fix", not "fixed" or "fixes")
# - Keep it under 50 characters
# [Optional body]: More detailed explanatory text, if necessary.
# - Wrap text at 72 characters
# - Explain the what, why, and how
# - Use bullet points if helpful
# [Optional footer(s)]: Additional metadata.
# - Include references to issues, e.g., "Closes #123"
# - Mention breaking changes, e.g., "BREAKING CHANGE: description"
# - Include co-authors or reviewers
# Signed-off-by [You]
签名重新提交
方法 1:git commit --amend(适用于未推送的提交)
如果你的提交 尚未推送(git push),可以修改最后一次提交并重新签名:
1 | $ git commit --amend --no-edit -S |
然后强制推送(如果已推送过)
1 | $ git push --force-with-lease |
方法 2:git rebase -i(适用于已推送的提交)
如果提交 已经推送,你可以用 rebase 修改历史记录:
交互式变基
1
$ git rebase -i HEAD~3 # 修改最近 3 个提交(可调整)
在编辑器里,把要修改的提交前的
pick改成edit(或e),保存退出。对每个
edit的提交执行1
2$ git commit --amend --no-edit -s -S # 补签名
$ git rebase --continue强制推送
(覆盖远程历史):
1
$ git push --force-with-lease
方法 3:git filter-branch(批量补签名)
如果要 批量修改多个提交,可以使用 filter-branch
1 | $ git filter-branch --commit-filter ' |
然后强制推送:
1 | $ git push --force-with-lease |
验证签名
检查是否成功补签:
1 | $ git log --show-signature -1 |
添加远程仓库
1 | $ git remote add [shortname] [url] |
提取远程仓库
Git 有两个命令用来提取远程仓库的更新。
1、从远程仓库下载新分支与数据:
1 | $ git fetch |
该命令执行完后需要执行 git merge 远程分支到你所在的分支。
2、从远端仓库提取数据并尝试合并到当前分支:
1 | $ git merge |
推送到远程仓库
推送你的新分支与数据到某个远端仓库命令:
1 | $ git push [alias] [branch] |
以上命令将你的 [branch] 分支推送成为 [alias] 远程仓库上的 [branch] 分支
删除远程仓库
删除远程仓库你可以使用命令:
1 | $ git remote rm [别名] |
GIt高级用法
还原工作区(文件内容)
git checkout – <file_name> 丢弃工作区的修改,并用最近一次的commit内容还原到当前工作区(对文件中内容的操作,无法对添加文件、删除文件起作用)
git checkout HEAD^ – <file_name> 将指定commit提交的内容(HEAD^表示上一个版本)还原到当前工作区
git checkout <branch_name> – <file_name> 将指定分支的指定提交内容还原到当前分支工作区
git checkout . 清除工作区没add的文件修改
git checkout --orphan <branch_name> 创建一个空分支
代码回退
restore(恢复) 针对的是暂存区的恢复(重点理解)
1 | ## 将不在暂存区的文件"撤销"更改(回滚到修改前) |
reset(重置) 针对的本地仓库的恢复 ``
1 | $ git reset --hard [commit Id] # reset --hard 会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容。 |
1 | $ git reset --hard origin # 删除所有本地未push的commit. 包括未commit的代码 |
HEAD^ 的意思是上一个版本,也可以写成HEAD~1
如果你进行了2次commit,想都撤回,可以使用HEAD~2
- –mixed
意思是:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作
这个为默认参数,git reset --mixed HEAD^和git reset HEAD^效果是一样的。- –soft
不删除工作空间改动代码,撤销commit,不撤销git add。- –hard
删除工作空间改动代码,撤销commit,撤销git add。
revert(恢复) 针对的是本地仓库的恢复
1、revert的原理是,在当前提交后面,新增一次提交,抵消掉上一次提交导致的所有变化。它不会改变过去的历史,所以是首选方式,没有任何丢失代码的风险
2、revert可以抵消上一个提交,那么如果想要抵消多个需要执行 git revert 倒数第一个commit id 倒数第二个commit
3、这个就常用于当你提交了一次commit之后发现提交的可能有问题就可以用到revert
4、还有一种情景是已经有很多人提交过代码,但是想改之前的某一次commit记录又不想影响后面的也可以使用revert,他会把你后面提交的记录都放到工作区只是合并的时候需要注意一点
git revert [commitId]
1 | 对commitId执行反向操作,恢复到commitId的上一个commitId的代码 |
git revert HEAD
1 | #提交记录 |
保存暂存区切换分支
1 | $ git stash |
1 | $ git stash pop |
1 | $ git stash 暂存状态 |
模板设置
1 | # 🌈 Git Commit Message Template |
安装依赖
1 | npm install --save-dev @commitlint/cli @commitlint/config-conventional husky commitizen cz-customizable |
package.json 配置
1 | { |
commitlint.config.js
1 | module.exports = { |
.cz-config.js
1 | module.exports = { |
1
2
3
4 rules: {
'scope-enum': [0], // 完全禁用scope校验
'scope-empty': [0] // 允许空scope
}
启用Git Hook
1 | npx --no-install commitlint --edit "\$1"' |







