一、Git命令

git clone

用于从远程仓库克隆项目。

  • HTTPS git clone https://github.com/GCS-ZHN/IDRBonline.git
  • SSH git clone git@github.com:GCS-ZHN/IDRBonline.git

可以选择只克隆指定分支

1
git clone --single-branch --branch main_dev https://github.com/GCS-ZHN/SoCube.git

git init

在当前文件夹建立git本地仓库,会出现.git本地文件夹。

git add

添加本地文件夹进入仓库。git init后需要add到index区域(一个压缩包文件)才能将内容递交加入仓库。添加本文件夹git add .。没有add的文件称为unstagegit status可以看到状态。add后称为stage

1
git add . # 将当前目录及其子目录的修改或新增加入

git commit -m

git add只是将项目加入暂存区index,利用commit最终将项目递交到本地仓库。参数为提交的备注评论。

git commit -am <COMMIT>可以用于删除。

git push

用于将本地仓库同步到远程仓库

  • 相同分支名 git push <远程主机名> <本地分支名>:<远程分支名>
  • 不同分支名 git push <远程主机名> <本地分支名>

git push还负责将tag进行远程推送

1
2
git push github :v1.3.1   ## 删除v1.3.1的github远端tag
git push github v1.3.1 ## 创建v1.3.1的github远端tag

git tag

tag管理,tag是与具体某个版本commit对应的可视化标签

1
2
3
4
5
git tag -d v1.3.1                               ## 删除本地v1.3.1的tag
git tag ## 列出所有本地标签
git tag -l "v1.8.5*" ## 列出通配的本地标签
git tag -a v1.4 [comit id] -m "my version 1.4" ## 创建附注标签, comit id缺省值为当前版本commit
git show v1.3.1 ## show命令查看标签

git pull

命令格式与push相似,将远程仓库内容拉取回本地仓库。

git remote

用于远程仓库的管理。用git remote -v可以查看当前远程仓库信息。

git remote add

git remote add <NAME> <URL>以指定名称添加远程仓库。信息加入到.git/config文件下。

例如

  • git remote add gitee https://gitee.com/GCSZHN/ideonline-web.git
  • git remote add node68 zhanghn@10.71.128.68:/public/home/zhanghn/VScodeProject/Web/Own/public/IDEonline-web

    git remote remove

    git remote remove <NAME>,删除指定名称的远程仓库。

    git reset

    该命令主要两个功能,以不同参数形式实现
  • 已经commit时,版本退回
  • 未commit时,回退到unstage或者回退到原先源码
    1
    2
    3
    git reset –-mixed  <版本>  [<文件>]   ## 撤销commit和add,不还原工作区
    git reset –-soft <版本> ## 撤销comit,不撤销add和还原工作区
    git reset --hard <版本> ## 撤销commit、add,并还原工作区
    例如,下面使用HEAD代表当前仓库版本,这是也是不加版本的默认版本。用于前述情况2,此时因为还原版本与当前版本相同,故不存在回撤commit,即类似于没有保存文件,还原文件更改。
    1
    2
    git reset file.txt
    git reset --mixed HEAD file.txt
    其中—mix为默认参数,可省略,该模式下可以指定还原某个文件。git reset --hard直接回退当前修改。而指定具体版本号则会实现第一点,回退版本。版本号(commit)可以通过git log来查看。
    1
    git reset eb43bf file.txt

    git checkout

    reset --hard有类似作用,例如git checkout -- git.md即可消除更改。但checkout对于多分支情况,不会变更每个分支所指代的commit,而是会切换当前HEAD指定分支。

    git filter-branch

    有另一个历史改写的选项,如果想要通过脚本的方式改写大量提交的话可以使用它——例如,全局修改你的邮箱地址或从每一个提交中移除一个文件。 这个命令是 filter-branch,它可以改写历史中大量的提交,除非你的项目还没有公开并且其他人没有基于要改写的工作的提交做的工作,否则你不应当使用它。 然而,它可以很有用。 你将会学习到几个常用的用途,这样就得到了它适合使用地方的想法。

filter-branch有很多陷阱,不再推荐使用它来重写历史。 请考虑使用git-filter-repo,它是一个Python脚本,相比大多数使用filter-branch的应用来说,它做得要更好。它的文档和源码可访问官方仓库获取。

git filter-repo

filter-branch的一个替代,可以通过pip git-filter-repo安装。例如下例使用其删除整个提交历史中的csv文件。

1
git filter-repo --force --invert-paths --path-regex .+\.csv

git stash

用于将当前修改暂存,保持工作区干净方便临时的checkout。

1
2
3
4
git stash # 将当前修改暂存
git stash apply # 将最近一次修改恢复
git stash pop # 将最近一次修改恢复并删除stash记录
git stash drop # 将最近一次修改stash记录删除

git clean

用于清楚当前工作区处于untrack状态的文件清除。

1
2
git clean -n # 仅仅展示要清除的文件而实际不删除
git clean -f -x # 忽略.gitigonre限制

git submodule

用于项目模块化,不同的子模块是不同的git仓库。

1
2
git submodule add git@github.com:GCS-ZHN/jvision.git dependency/jvision # 添加子模块
git submodule update --init # 更新子模块,如果没有被拉取到本地会被拉取

子模块会在.git/modules/模块中看到对应的git记录。.git/config中和.gitmodules中可以看到子模块的配置。如果需要剔除子模块,需要将上述三者同时删除。

二、服务器上自建git仓库

通过git init事实上就建立了一个本地当前目录仓库(会产生.git子文件夹),而git init --bare repo.git则在当前目录下建立了一个无workspace的仓库,目录名repo.git。

git命令可以基于HTTPS协议或是SSH协议进行访问,且根据url配置自动识别哪种协议。对于自己服务器建立的git仓库,建议就直接使用SSH协议,现成无需配置。例如用户zhanghn/public/home/zhanghn/repo是一个git仓库(下面有.git子文件夹或者bare模式的配置文件),可以用类ssh格式URL访问。

1
git clone zhanghn@10.71.128.68:/public/home/zhanghn/repo

在这里,和ssh一样,倘若配置了ssh密钥免密访问(ssh-keygen),则不用密码,否则输入用户密码即可。我们与gitee(码云)和github提供的SSH协议URL
1
2
git@gitee.com:GCSZHN/IDRBonline.git
git@github.com:GCS-ZHN/IDRBonline.git

实际上,gitee和github是为我们专门创建了一个git用户(对应zhanghn),且仓库目录都以.git结尾(相当于是一种规范,clone时会自动去掉,得到真实项目名)。

事实上,git仓库关键的是.git文件夹下的一下记录一系列commit状态信息。不同节点仓库通过.git下的commit信息来通过变更。因此必须先从远程仓库pull下来保持一致,才能利用push修改提交远程仓库。

1
2
3
4
git init                   ## 建立本地仓库,出现.git
git add . ## 加入新增文件到缓冲区,准确commit
git commit -am "commit" ## commit到本地仓库,即添加变化信息去本地仓库
git push <远程仓库> <分支> ## push同步更新到远程仓库,若未获取最新远程,必须先将远程仓库pull下来

对于github、gitee等专业的git托管仓库,在提交远程(push)后,会自动将更新合并到对应分支的工作区。这类似docker容器的文件分层一样,git会记录的实际上是修改差异(在.git文件夹下),默认不会自动更改工作区(即我们看到的真实项目)。

三、github LFS服务

默认情况下,github单个文件上传大小限制是100M,仓库单个限制是1G。这样的设计是为了服务器性能考虑,同时也是因为git的分布式版本控制原因。大文件版本堆积会影响主仓库的性能。为支持一些必要的大文件上传,github提供了LFS(large file service)扩展,用于支持大文件上传。此时主仓库保存的大文件其实是一个文件信息戳(download zip可以看到文件大小是KB级别,可以用文本编辑器查看),真实的大文件被github另行存储了。版本更迭只需要更新主仓库的文件信息戳。

1
2
3
version https://git-lfs.github.com/spec/v1
oid sha256:64b2bb58b840271d26d7f8af5b23bfa92e8aecfe0e4fa2d5bdef5b5a23e8b171
size 150631424

lfs的启用

1
2
apt-get install git-lfs  # 下载安装扩展
git lfs install # git中启用LFS扩展

添加大文件

1
2
3
git lfs track        # 查看当前当做大文件的文件类型
git lfs track *h5 # 添加新的大文件

最后你就可以通过正常的git操作来上传与下载,此时git clone等操作等效于git lfs clone等操作。

四、启用GPG签名验证

GPG签名验证可以保障提交的tag和commit的安全性,防止非法提交。详细操作步骤请参考GitHub文档,但值得一提的是,在Windows上使用GPG签名,首先需要安装Gpg4win,可以通过choco install Gpg4win安装,或者从gnupg官网下载安装。同时,需要指定git使用的gpg。

1
2
3
4
5
6
where.exe gpg # C:\Program Files (x86)\GnuPG\bin\gpg.exe
git config --global gpg.program "c:/Program Files (x86)/GnuPG/bin/gpg.exe"
git config --global commit.gpgsign true # 默认给commit启动GPG
git config --global tag.gpgsign true # 默认给tag启动GPG
git config --global user.signingkey <GPG-SECRET-KEY> # 指定GPG密钥
gpg --armor --export <GPG-SECRET-KEY> # 导出GPG方便上传至github

参考文献

  1. 如何使用git命令行上传项目到github
  2. git的reset和checkout的区别
  3. git重写历史