Git
Git
一、git基本使用
1、commit
[root@node01 project]# git add 1.txt
[root@node01 project]# git commit -m "create new 1.txt"
[master (root-commit) 3e8ce87] create new 1.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 1.txt
2、diff文件
[root@node01 project]# git diff 1.txt
diff --git a/1.txt b/1.txt
index e69de29..21d56a0 100644
--- a/1.txt
+++ b/1.txt
@@ -0,0 +1 @@
+1111111111111111
3、版本回退
在进行版本回退时,使用HEAD代表当前版本,HEAD^
代表上一个版本,HEAD^^
代表上上个版本,还可以使用HEAD~10代表前10个版本
[root@node01 project]# git reset --hard HEAD^
HEAD is now at fdf9d68 add new 1111
[root@node01 project]#
[root@node01 project]# cat 1.txt
1111111111111111
[root@node01 project]#
也可以使用如下命令格式:
[root@node01 project] git reset --hard <commit_id>
[root@node01 project]# git reflog 1.txt
fdf9d68 HEAD@{0}: reset: moving to HEAD^
996cc77 HEAD@{1}: commit: add new 222
fdf9d68 HEAD@{2}: commit: add new 1111
3e8ce87 HEAD@{3}: commit (initial): create new 1.txt
[root@node01 project]#
[root@node01 project]# git reset --hard 996cc77
4、撤销更改
1)对于尚未添加到暂存区的修改,可直接通过编辑原文件或者使用git checkout -- <file>
的方式进行撤销
[root@node01 project]# git checkout -- 1.txt
[root@node01 project]# git status
# On branch master
nothing to commit, working directory clean
2)对于已经添加到暂存区,但还没有git commit的修改,可使用git reset HEAD <file>
的方式撤销
[root@node01 project]# vim 1.txt
[root@node01 project]# git add 1.txt
[root@node01 project]# git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: 1.txt
#
[root@node01 project]# git reset HEAD 1.txt
Unstaged changes after reset:
M 1.txt
[root@node01 project]# git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: 1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
[root@node01 project]# git checkout -- 1.txt
[root@node01 project]# git status
# On branch master
nothing to commit, working directory clean
[root@node01 project]# cat 1.txt
1111111111111111
22222222222222222
3333333333333
3)对于已经添加到暂存区,并已经提交的修改可通过git reset –hard <commit_id>的方式进行撤销
[root@node01 project]# vim 1.txt
[root@node01 project]# git add 1.txt
[root@node01 project]# git commit -m "add new 44444444"
[master 240af53] add new 44444444
1 file changed, 1 insertion(+)
[root@node01 project]# git reflog 1.txt
240af53 HEAD@{0}: commit: add new 44444444
5424335 HEAD@{1}: commit: add new 333333
996cc77 HEAD@{2}: reset: moving to 996cc77
3e8ce87 HEAD@{3}: reset: moving to 3e8ce87
996cc77 HEAD@{4}: reset: moving to 996cc77
fdf9d68 HEAD@{5}: reset: moving to HEAD^
996cc77 HEAD@{6}: commit: add new 222
fdf9d68 HEAD@{7}: commit: add new 1111
3e8ce87 HEAD@{8}: commit (initial): create new 1.txt
[root@node01 project]#
[root@node01 project]#
[root@node01 project]# git reset --hard 5424335
HEAD is now at 5424335 add new 333333
二、git配置
1、配置基本信息
[root@localhost srv]# git config --global user.name 'sugar'
[root@localhost srv]# git config --global user.email 't@local.com'
[root@localhost srv]# git config --global color.ui true #配置显示的颜色,方便看到更改的信息
[root@localhost srv]# git config --global core.ignorecase false # 配置大小写敏感,git默认大小写不敏感
2、gitconfig配置文件
[user]
name = sugar
email = t@local.com
# signingkey = DCE96Cxxxxxxxxxxxxxxxxxxxxxxxx
#[commit]
# gpgsign = true
# ~/github/ 目录下的项目使用~/github/.gitconfig下的gitconfig配置文件
[includeIf "gitdir:~/github/"]
path = ~/github/.gitconfig
[includeIf "gitdir:~/my-prod/"]
path = ~/my-prod/.gitconfig
[init]
defaultBranch = main
[color]
ui = true
[alias]
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
[alias]
# status
st = status
ss = status --short --branch
# stash
sh = stash
shp = stash pop
shl = stash list
shs = stash save
sha = stash apply
std = stash drop
# branch
br = branch
bra = branch -a
brm = branch -m
co = checkout
cob = checkout -b
sw = switch
swc = switch -c
# remote
ra = remote add
rao = remote add origin
ru = remote set-url
ruo = remote set-url origin
rv = remote -v
# fetch
fe = fetch
fep = fetch -p
fo = fetch origin
fop = fetch origin -p
# merge
mr = merge
mnc = merge --no-commit
# msq = merge --squash
# commit
cm = commit -m
# config user and mail
user = config user.name
mail = config user.email
[url "git@github.com:username"]
insteadOf = https://github.com/username
# 强制https转ssh协议
[url "ssh://git@local.com/"]
insteadOf = https://local.com/
[core]
excludesfile = ~/.gitignore_global
autocrlf = input
quotepath = false
ignorecase = false
editor = vim
# sshCommand = ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
[i18n "commit"]
encoding = utf-8
[i18n]
logoutputencoding = utf-8
[http "https://github.com"]
proxy = socks5://127.0.0.1:8888
[http]
proxy = http://127.0.0.1:8889
[https]
proxy = http://127.0.0.1:8889
3、windows上终端打开出现乱码
cmd配置
git config --global core.quotepath false
git config --global gui.encoding utf-8
git config --global i18n.commit.encoding utf-8
git config --global i18n.logoutputencoding utf-8
# bash 环境下
export LESSCHARSET=utf-8
# cmd环境下:
set LESSCHARSET=utf-8
powershell配置
git config --global core.quotepath false
git config --global gui.encoding utf-8
git config --global i18n.commit.encoding utf-8
git config --global i18n.logoutputencoding utf-8
$env:LESSCHARSET='utf-8'
git bash
sugar@sugar MINGW64 /e/Desktop/company/github (master)
$ cat /etc/bash.bashrc
alias ls='ls -F --color --show-control-chars'
NOW_DIR="E:\Desktop"
cd ${NOW_DIR}
export LESSCHARSET=utf-8
三、分支管理
git版本库所有的操作都是运行在分支上,git仓库创建时会建立默认的分支,名称为master;所有的操作都在master分支上进行 在对版本库中的文件进行操作时,可以创建不同的分支,不同的操作运行在不同的分支上,不同分支上的操作不会相互干扰,操作进行完成后,可以合并不同分支上的操作
1、创建分支
[root@node01 project]# git checkout -b game
Switched to a new branch 'game'
[root@node01 project]#
[root@node01 project]# git branch
dev
* game
master
1)远程chekout到本地
[root@node01 project]# git checkout origin/develop -b develop
2)删除分支
# 删除本地分支
[root@node01 project]# git branch -d release-1.1.0
# 强制删除
[root@node01 project]# git branch -D release-1.1.0
# 删除远程分支
[root@node01 project]# git push origin --delete release-1.1.0
或者
[root@node01 project]# git push origin :release-1.1.0
3)根据hash值进行checkout
git checkout d21a8c517ca3xxxxxxxxxxxxxxxxxxxxxxxxxxx
4)分支合并
切换到准备合并后的分支,合并其他分支到当前分支
[root@node01 project]# git merge dev
Updating bb6fb7a..d83dae8
Fast-forward
1.txt | 2 ++
1 file changed, 2 insertions(+)
四、tag管理
打标签,用于仓库某个提交打上标签,以表示其特殊性。比较有代表性的是人们会使用这个功能来标记发布结点( v1.0
、 v2.0
等等)
1、查看本地已有标签
[root@localhost github_web]# git tag
4.101.0
4.103.0
4.103.1
列出所有标签 -l
或者--list
,指定某些提交信息-l "v4.4*"
2、创建tag
Git 支持两种标签:
-
轻量标签(lightweight)
-
附注标签(annotated)。
轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。但是如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。
附属标签:
git tag -a v1.4 -m "my version 1.4"
查看详细信息
git show v1.4
输出显示了打标签者的信息、打标签的日期时间、附注信息,然后显示具体的提交信息。
轻量标签:
另一种给提交打标签的方式是使用轻量标签。 轻量标签本质上是将提交校验和存储到一个文件中——没有保存任何其他信息。 创建轻量标签,不需要使用 -a
、-s
或 -m
选项,只需要提供标签名字:
$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
这时,如果在标签上运行 git show
,你不会看到额外的标签信息。 命令只会显示出提交信息:
$ git show v1.4-lw
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <t@local.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
后期打标签
git tag -a v1.2 9fceb02
共享标签
默认情况下,git push
命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。 这个过程就像共享远程分支一样——你可以运行 git push origin <tagname>
。
$ git push origin v1.5
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5
如果想要一次性推送很多标签,也可以使用带有 --tags
选项的 git push
命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。
$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
3、删除标签
要删除掉你本地仓库上的标签,可以使用命令 git tag -d <tagname>
。 例如,可以使用以下命令删除一个轻量标签:
$ git tag -d v1.4-lw
Deleted tag 'v1.4-lw' (was e7d5add)
注意上述命令并不会从任何远程仓库中移除这个标签,你必须用 git push <remote> :refs/tags/<tagname>
来更新你的远程仓库:
方法一:git push <remote> :refs/tags/<tagname>
$ git push origin :refs/tags/v1.4-lw
To /git@github.com:username/project.git
- [deleted] v1.4-lw
上面这种操作的含义是,将冒号前面的空值推送到远程标签名,从而高效地删除它。
方法二:直接删除远程标签
$ git push origin --delete <tagname>
4、检出标签
检出标签为一个分支,格式为git checkout -b branch_name tag_name
git checkout -b version2 v2.0.0
5、.git 目录
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ └── ...
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
- config (配置)该文件包含你的仓库配置,比如远程的 url ,你的邮箱和用户名等。每次你在控制台使用 git config… 都会对这里产生影响。
- description(描述)供 gitweb ( github 的一种前身) 使用,显示仓库的描述。
- hooks (钩子)这是一个有趣的特性。 Git 提供了一套脚本,可以在每个有意义的 Git 阶段自动运行。这些被称为钩子的脚本可以在提交 (commit)、变基 (rebase)、拉取 ( pull ) 操作的前后运行。脚本命预示着它的执行时机。如我们可以编写 pre-push 的作为钩子,进行推送代码前的检查。
- info (信息)你可以将不想被 git 管理的文件记录到 .gitignore 文件中。排除文件的意思是不想共享这个文件。例如你不想共享你的 IDE 自定义配置,将其添加到 .gitignore 文件中即可。
五、cherry-pick
参考:https://www.ruanyifeng.com/blog/2020/04/git-cherry-pick.html
对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。
这时分两种情况。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge
)。另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 Cherry pick。
1、基本语法
git cherry-pick
命令的作用,就是将指定的提交(commit)应用于其他分支。
$ git cherry-pick <commitHash>
上面命令就会将指定的提交commitHash
,应用于当前分支。这会在当前分支产生一个新的提交,当然它们的哈希值会不一样。
举例来说,代码仓库有master
和feature
两个分支。
a - b - c - d Master \ e - f - g Feature
现在将提交f
应用到master
分支。
# 切换到 master 分支 $ git checkout master # Cherry pick 操作 $ git cherry-pick f
上面的操作完成以后,代码库就变成了下面的样子。
a - b - c - d - f Master \ e - f - g Feature
从上面可以看到,master
分支的末尾增加了一个提交f
。
git cherry-pick
命令的参数,不一定是提交的哈希值,分支名也是可以的,表示转移该分支的最新提交。
$ git cherry-pick feature
上面代码表示将feature
分支的最近一次提交,转移到当前分支。
操作示例:
[sugar@centos-7 git-test]$ git log -1
commit dcf3a215fd6ba3288ad21584d2112bdab5a713b4
Author: sugar <cccc@gmail.com>
Date: Sun Sep 12 14:29:26 2021 +0800
feat: v1 version 1s add
[sugar@centos-7 git-test]$ git checkout master
Switched to branch 'master'
[sugar@centos-7 git-test]$ git log
commit 31da420cc2d2ae6094f88e368a72f0353541d89f
Author: sugar <cccc@gmail.com>
Date: Sun Sep 12 14:25:43 2021 +0800
feat: 第一此增加
[sugar@centos-7 git-test]$ git cherry-pick dcf3a215fd6ba3288ad21584d2112bdab5a713b4
[master fa78bb0] feat: v1 version 1s add
1 file changed, 2 insertions(+), 1 deletion(-)
[sugar@centos-7 git-test]$ ls
cccc.txt
[sugar@centos-7 git-test]$ git log -1
commit fa78bb090d3221ba2ff9cae59efa1f8691677115
Author: sugar <cccc@gmail.com>
Date: Sun Sep 12 14:29:26 2021 +0800
feat: v1 version 1s add
2、转移多个commit
Cherry pick 支持一次转移多个提交
[sugar@centos-7 git-test]$ git cherry-pick <HashA> <HashB>
连续提交多个commit
# 提交A到B的commit,但不包含A;提交A必须早于提交B,否则命令将失败,但不会报错。
[sugar@centos-7 git-test]$ git cherry-pick A..B
# 提交A到B的commit,包含A
[sugar@centos-7 git-test]$ git cherry-pick A^..B
3、参数
git cherry-pick
命令的常用配置项如下。
(1)-e
,--edit
打开外部编辑器,编辑提交信息。
(2)-n
,--no-commit
只更新工作区和暂存区,不产生新的提交。
(3)-x
在提交信息的末尾追加一行(cherry picked from commit ...)
,方便以后查到这个提交是如何产生的。
(4)-s
,--signoff
在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作。
(5)-m parent-number
,--mainline parent-number
如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,因为它不知道应该采用哪个分支的代码变动。
-m
配置项告诉 Git,应该采用哪个分支的变动。它的参数parent-number
是一个从1
开始的整数,代表原始提交的父分支编号。
$ git cherry-pick -m 1 <commitHash>
上面命令表示,Cherry pick 采用提交commitHash
来自编号1的父分支的变动。
一般来说,1号父分支是接受变动的分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)。
4、代码冲突
如果操作过程中发生代码冲突,Cherry pick 会停下来,让用户决定如何继续操作。
1)--contine
用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .
),第二步使用下面的命令,让 Cherry pick 过程继续执行。
$ git cherry-pick --continue
2)--abort
发生代码冲突后,放弃合并,回到操作前的样子。
3)--quit
发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子。
5、转移到另外一个仓库
Cherry pick 也支持转移另一个代码库的提交,方法是先将该库加为远程仓库。
# 添加一个远程仓库
$ git remote add target git://gitUrl
# 将远程仓库的代码抓取到本地
$ git fetch target
# 检查一下要从远程仓库转移的提交,获取它的哈希值
$ git log target/master
# 使用git cherry-pick命令转移提交
$ git cherry-pick <commitHash>
六、合并commit
在使用 Git 作为版本控制的时候,我们可能会由于各种各样的原因提交了许多临时的 commit,而这些 commit 拼接起来才是完整的任务。那么我们为了避免太多的 commit 而造成版本控制的混乱,通常我们推荐将这些 commit 合并成一个。
1、查看提交历史
$ git log
commit 3ca6ec340edc66df13423f36f52919dfa3......
commit 1b4056686d1b494a5c86757f9eaed844......
commit 53f244ac8730d33b353bee3b24210b07......
commit 3a4226b4a0b6fa68783b07f1cee7b688.......
2、git rebase
想要合并1-3条,有两个方法
1)从HEAD版本开始往过去数3个版本
$ git rebase -i HEAD~3
2)指名要合并的版本之前的版本号
$ git rebase -i 3a4226b
请注意3a4226b
这个版本是不参与合并的,只是把它当做一个坐标
3、选择要合并的提交
p是保留,s是合并
1)执行了rebase命令之后,会弹出一个窗口,头几行如下:
pick 3ca6ec3 '注释**********'
pick 1b40566 '注释*********'
pick 53f244a '注释**********'
2)将pick改为squash或者s,之后保存并关闭文本编辑窗口即可。改完之后文本内容如下:
pick 3ca6ec3 '注释**********'
s 1b40566 '注释*********'
s 53f244a '注释**********'
3)然后保存退出,Git会压缩提交历史,如果有冲突,需要修改,修改的时候要注意,保留最新的历史,不然我们的修改就丢弃了。修改以后要记得敲下面的命令:
pick 3ca6ec3 '注释**********'
s 1b40566 '注释*********'
s 53f244a '注释**********'
4)冲突解决
然后保存退出,Git会压缩提交历史,如果有冲突,需要修改,修改的时候要注意,保留最新的历史
git add .
# 继续合并
git rebase --continue
# 放弃合并
git rebase --abort
如果没有冲突,或者冲突已经解决,则会出现如下的编辑窗口:
# This is a combination of 4 commits.
#The first commit’s message is:
注释......
# The 2nd commit’s message is:
注释......
# The 3rd commit’s message is:
注释......
# Please enter the commit message for your changes. Lines starting # with ‘#’ will be ignored, and an empty message aborts the commit.
5)检查
git log查看 commit 历史信息,查询commit的信息
七、Git Hook
Git Hook 也分为两个端: 客户端和服务端。
客户端的 Git Hook 就是工作在我们本地机器的,服务端的 Git Hook 则是工作在我们提交到远程的服务器仓库中。
客户端 Git Hook:
- pre-commit: 执行git commit命令时触发,常用于检查代码风格
- prepare-commit-msg: 触发于 commit message 编辑器呼起前 ,default commit message创建后,常用于生成默认的标准化的提交说明
- commit-msg: 开发者编写完并确认commit message后触发,常用于校验提交说明是否标准
- post-commit: 整个git commit完成后触发,常用于邮件通知、提醒
- applypatch-msg: 执行git am命令时触发,常用于检查命令提取出来的提交信息是否符合特定格式
- pre-applypatch: git am提取出补丁并应用于当前分支后,准备提交前触发,常用于执行测试用例或检查缓冲区代码
- post-applypatch: git am提交后触发,常用于通知、或补丁邮件回复(此钩子不能停止git am过程)
- pre-rebase: 执行git rebase命令时触发
- post-rewrite: 执行会替换commit的命令时触发,比如git rebase或git commit –amend
- post-checkout: 执行git checkout命令成功后触发,可用于生成特定文档,处理大二进制文件等
- post-merge: 成功完成一次 merge行为后触发
- pre-push: 执行git push命令时触发,可用于执行测试用例
- pre-auto-gc: 执行垃圾回收前触发
服务端 Git Hook:
- pre-receive: 当服务端收到一个 push 操作请求时触发,可用于检测 push 的内容
- update: update 脚本和 pre-receive 脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。 假如推送者同时向多个分支推送内容,pre-receive 只运行一次,相比之下 update 则会为每一个被推送的分支各运行一次。
- post-receive: post-receive 挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器,或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。
使用git hook
Git Hook 本身自带有脚本,会存放在仓库 .git/hooks 文件夹中,目录一般是这样的:
- YourGitRepo
|- .git
|- hooks
|- hooks--commit-msg.sample
|- hooks--post-update.sample
...
注意如果是 sample 文件,要去掉 .sample 后缀,变成前面 Git Hook 分类
中提到对应的操作来作为文件名。
比如我要做的校验 commit 的提交信息,那么使用的 Git Hook 脚本名应该为 commit-msg
.
在 hooks--commit-msg.sample
里的内容为:
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
上面说明里有一些基本说明, 这里获得的 $1 参数,其实是存放 commit msg 内容的文件路径,为 .git/COMMIT_EDITMSG
.
利用命令:
msg=$(cat $1)
就能取到 commit 的信息,稍作修改,就能达到我说的,校验团队 commit 信息的规范的目的了。
Git Hook 不生效
如果遇到不起作用的,可能脚本没有打开执行权限,导致没办法执行。我就是这样的情况。
cd 到 .git/hooks 目录下,执行 chmod 777
命令即可,如:
chmod 777 commit-msg
八、Git GC
清理不必要的文件并优化本地存储库
参考链接:Git - 管理 | Administration - git gc - 开发者手册 - 云+社区 - 腾讯云 (tencent.com)
Git的底层并没有采用 CVS、SVN 底层所采用的那套增量式文件系统,而是采用一套自行维护的存储文件系统。当文件变动发生提交时,该文件系统存储的不是文件的差异信息,而是文件快照,即整个文件内容,并保存指向快照的索引。这种做法,提高 Git 分支的使用效率;但也容易导致代码仓库中内容重复程度过高,从而仓库体积过大。当遇到这种情况时,或者需要将仓库推送到远程主机时,就需要Git中的gc(garbage collect)功能,也就是垃圾回收功能。
大体来说,当运行 “git gc” 命令时,Git会收集所有松散对象并将它们存入 packfile,合并这些 packfile 进一个大的 packfile,然后将不被任何 commit 引用并且已存在一段时间 (数月) 的对象删除。 此外,Git还会将所有引用 (references) 并入一个单独文件。
就细节而言,Git做了这几件事:
- pack_refs 过程
- reflog expire 过程
- repack 过程
- prune 过程
- rerere 过程
概要:
git gc [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune] [--force]
描述:
在当前存储库中运行许多内务处理任务,例如压缩文件修订(以减少磁盘空间并提高性能)并移除可能由之前git add
调用创建的不可达对象。
鼓励用户在每个存储库中定期运行此任务,以保持良好的磁盘空间利用率和良好的操作性能。
一些git命令可能会自动运行git gc
; --auto
详细信息请参阅下面的标志。如果您知道自己在做什么,并且所有您想要的都是永久禁用此行为而无需进一步考虑,请执行以下操作:
$ git config --global gc.auto 0
选项:
- –aggressive
通常git gc
运行速度很快,同时提供良好的磁盘空间利用率和性能 此选项将导致git gc
更积极地优化存储库,但花费更多时间。这种优化的效果是持久的,所以这个选项只需要偶尔使用; 每隔几百个变更集左右。
- –auto
使用此选项,git gc
检查是否需要进行任何清洁工作; 如果没有,它会退出而不执行任何工作。一些git命令git gc --auto
在执行可能会产生许多松散对象的操作之后运行。
如果存储库中的松散对象太多或包装太多,则需要进行内务处理。如果松散对象的数量超过了gc.auto
配置变量的值,则所有松散对象都将使用组合到一个包中git repack -d -l
。将值设置gc.auto
为0将禁用自动填充松散物体。
如果包装数量超过了价值gc.autoPackLimit
,那么现有包装(标有.keep
文件的包装除外)将通过使用-A
选项合并到一个包装中git repack
。设置gc.autoPackLimit
为0将禁用自动合并包装。
- –prune=
修剪比日期更旧的松散对象(默认为2周前,可由配置变量覆盖gc.pruneExpire
)。–prune =不管年龄大小,都修剪松散的物体,并且如果另一个进程同时写入存储库,则会增加腐败风险; 请参阅下面的“注意事项”。–prune默认打开。
- –no-prune
不要修剪任何松动的物体。
- –quiet
取消所有进度报告。
- –force
git gc
即使可能有另一个git gc
实例在此存储库上运行,也强制运行。
注意:
git gc
尽量不要删除在存储库中任何位置引用的对象。特别是,它不仅会保存当前一组分支和标记所引用的对象,还会保留由索引引用的对象,远程跟踪分支,git filter-branch
refs / original /中保存的引用或reflogs(可引用分支中的提交后来修改或倒带)。如果您希望某些对象被删除而不是,请检查所有这些位置,并决定在您的情况下删除这些引用是否有意义。
另一方面,当git gc
与另一个进程同时运行时,可能会删除另一个进程正在使用但尚未创建引用的对象。这可能会导致其他进程失败或者可能会损坏存储库,如果其他进程稍后添加对已删除对象的引用。Git有两个功能可以显着缓解这个问题:
-
--prune
保留修改时间比日期更新的任何对象以及可从其访问的所有对象。 -
将对象添加到数据库的大多数操作都会更新对象的修改时间(如果该对象已存在,以便应用#1)。
然而,这些功能并不能提供完整的解决方案,因此,同时运行命令的用户必须忍受一些腐败风险(实践中似乎很低),除非他们关闭自动垃圾收集git config gc.auto 0
九、Git gpg签名
# 查看gpg密钥
[root@local ~]# gpg --list-key
/root/.gnupg/pubring.kbx
------------------------
pub rsa4096 2021-08-23 [SC]
C40EA42A60xxxxxxxxxxxxxxxxxx
uid [ 绝对 ] cccc (local) <t@local.com>
sub rsa4096 2021-08-23 [E]
pub rsa4096 2021-08-23 [SC]
3CB22116355xxxxxxxxxxxxxxxxxx
uid [ 绝对 ] tom (github) <t@local.cc>
sub rsa4096 2021-08-23 [E]
配置使用gpg签名
# git 配置使用gpg签名
git config --global user.signingkey <gpg-key-id>
# 提交是否强制 GPG,带上--global 是作用全局,局部的去除--global
[root@sugar2 ~]# git config --global commit.gpgsign true
# commit 提交设置GPG签名,如果没有设置强制,则需要加上-S
[root@sugar2 ~]# git commit -S -m “commit message"
# 在github上签名的提交将显示包含“ Verified”
问题:
[root@sugar ssl]# git commit -m "init repo"
error: gpg 数据签名失败
fatal: 写提交对象失败
参考链接:https://zhuanlan.zhihu.com/p/97984430
解决办法:export GPG_TTY=$(tty)
在环境变量里增加一项GPG_TTY