Git的由来:
Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理,也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。
常见的代码托管平台:
Git 常见命令:
git init
在本地目录中初始化一个新的Git仓库
git config
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。
git config --global user.name "your username"
git config --global user.email "your email"
更改默认编辑器
git config --global core.editor nano
git clone
用于将远程仓库的代码克隆到本地,以下是命令中各个参数的含义:
<url>
克隆某个地址(url)的仓库,远程仓库的地址可以是本地的目录,也可以是例如github,giteee,gitlab一类的代码托管平台
--depth=<number>
克隆仓库并且保留number条提交历史,number在此处即表达我们克隆的深度。
-b <branch>
克隆指定分支下的仓库内容
例如我们要克隆LineageOS
的内核源码,指定lineage-21
分支,且仅保留最近一个提交,则需要输入:
git clone -b lineage-21 https://github.com/LineageOS/android_kernel_xiaomi_sdm845 --depth=1
git add
添加某个文件,或者目录到暂存区,用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中
git add [file1] [file2]
添加指定目录(文件)到暂存区,包括子目录:
git add [dir]
添加当前目录下的所有文件到暂存区:
git add .
git status
查看当前仓库的状态,此时git会在你的终端输出以下内容
此处演示为英文,如果您的git终端输出为中文也是同理的
On branch master No commits yet Changes to be committed: (use “git rm --cached <file>...” to unstage) new file: makefile
输出内容分别为
您目前所在的分支 目前的提交 需要更改的内容 新增的文件 修改的文件 删除的文件
git commit
用于将暂存区我们保存的更改文件添加到本地仓库,并且会生成一条提交(commit)
提交暂存区的更改到本地仓库
git commit -m "message"
[注] message 可以是你的备注信息
提交暂存区中的指定文件到本地仓库
如果你没有使用上述git add
命令暂存你的修改文件,可以使用
git commit -a
进行直接提交
git checkout
- 用于分支切换
切换分支:
git checkout <branch-name>
git checkout <branch-name>
例如在您的仓库中有这几个分支:
-> master (Default) backup test
您当前处于 master 分支,如果想要切换到test分支,我们可以使用
git checkout test
- 用于检出文件
将指定的文件恢复到最新的提交状态,撤销你对其的更改
git checkout -- <file>
git push
用于将本地的分支版本上传到远程仓库并进行合并
git push <remote-host-name> <local-branch-name>:<remote-branch-name>
remote-host-name:远程主机名
local-branch-name:本地分支名
例如,当你的远程主机名为origin ,本地分支名为master,远程分支名为master时:
git push origin master:master
例如,当你的rhost名为origin 本地分支名为master远程分支名为master时:
本地和远程分支名相同,上述命令可以简写为:
git push origin master
当你的远程版本与本地版本有差异,无法直接push时,你可以使用--force 参数来进行强制推送
git push --force origin master
--force 此处可以直接简单化为 -f
如果你想要删除主机内的某个分支,你可以使用--delete参数
git push origin --delete <branch-name>
git diff
用于比较当前工作区与上一个版本之间的差异
例如:(此处仅做不恰当举例,Makefile不是这样乱写的)
diff --git a/makefile b/makefile index fbb8c85..d65c7eb 100644 --- a/makefile +++ b/makefile @@ -1 +1,2 @@ 114514 +1919180
git log
用于查看提交的历史
例如当你进行一次提交之后,执行 git log
终端会输出
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -> master) Author: luluzzy <1054438588@qq.com> Date: Thu Feb 15 21:28:47 2024 +0800 initial commit: add makefile
这些输出分别为
commit sha1 hash: 针对你这个提交的 commit id Author: commit 作者名称 <you@example.com> Date: commit 日期 commit: 名称
关于sha1_hash的介绍请看这里[1]
当有多次提交之后,如果我们想要翻之前的提交历史,难免会因为终端输出的内容过多而难以查看翻阅
此时我们可以使用--online
参数来简化输出,此时仅会输出: sha1哈希值 + commit的名称
例如
347595d (HEAD -> master) modify makefile 3a5b0d1 initial commit: add makefile
git cherry-pick
cherry-pick (遴选) 和它的名称一样,挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改,移植到当前的分支。
如果我们想在我们正在开发的版本上,添加一个其他版本中的功能代码。就可以使用 cherry-pick ,将这个功能相关的 commit 提取出来,合入该版本。
git cherry-pick <commit-id>
当我们执行完 cherry-pick
操作之后,会自动生成一个commit
以及对应新的commit-id
在顺利的情况下我们可以直接通过,但如果遇到代码等因为变量名,写法等不同的情况,cherry-pick
大概率会报错,此时我们需要进行报错处理。
第一种方案是手动修改
我们可以先使用git status
检查当前遴选时冲突的文件
然后 git checkout --ours filename
然后按照提交的修改内容进行手动修改
随后使用git add
命令将文件重新加入暂存区
再使用
git cherry-pick --continue
命令让 cherrypick 操作继续执行。
第二种方案是直接退出cherry-pick
进程,一般适用于冲突文件实在太多了难以按照方案一处理的情况。
需要注意的是,如果您当前正在遴选的提交在该分支已经存在也会冲突,在这种情况下,您需要解决冲突并手动解决问题。
git cherry-pick --abort
git fetch
git fetch 命令用于从远程获取仓库。
git merge
git merge
是用来把分叉的提交历史放回到一起(合并)的方式。
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。
本
git pull
用于从远程获取代码并合并本地的版本。
git pull
其实就是git fetch
和git merge FETCH_HEAD
的简写。
格式如下:
git pull <remote-host-name> <remote-branch-name>:<local-branch-name>
git rebase
用于需要修改历史上某一项commit
git rebase -i HEAD~<commit number>
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器,若未配置则是默认,vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。 有以下操作:
1.edit,顾名思义编辑此commit,替换完保存后请修改内容,使用git add
或vscode,github desktop将修改文件添加到暂存区,之后命令行执行git commit --amend
这样commit就修改成了
2.squash,合并几个提交,确认一个父提交,将要合并的commit,从下向上替换字符串,会从下向上合并(方位指的是git rebase
后弹出的编辑器)
3.drop,需要移除的commit
git subtree
子树,在Android开发中多用于Kernel侧更改,如跟踪audio模块等
git subtree add --prefix=<目录> <仓库地址> <远程分支>
如果需要更新远程库时
git subtree pull --prefix=<目录> <仓库地址> <远程分支>
git submodule
子模块功能的概述
git submodule
允许在自己的Github仓库里加入别人的github仓库,作为自己仓库的子仓库(即submodule)。
为什么我们会需要使用子模块?当我们维护一个项目时有可能遇到以下情况,例如维护某款机型的KernelSU内核,我们需要将KernelSU导入至我们的内核源码中,如果我们直接clone进去容易带来一个问题,如果KernelSU更新了怎么办?此时我们便可以使用子模块来解决这个问题
git submodule
允许在git仓库里存放别人仓库的url,作为自己的子模块,其核心内容是在Git仓库里面加入一个.gitmodules
文件,里面会记录各个submodule的名字,路径,以及对应链接。
加入子模块
git submodule add <url> <path>
此时 .gitmodules
内会自动生成以下内容
[submodule "xxx"]
path = xxx
url = xxx
初始化子模块
git submodule init
更新子模块
git submodule update
Git进阶
GPG key
简介
平时在Github上摸鱼的时候,是不是经常能看见如下图所示,有一个绿色的"Verified"字样,看着很酷,实际上这是为了确保commit为开发者本人所写的进行的GPG签名。
因为Git的默认机制,任何人都可以通过你的邮箱和用户名创建虚假的commit,甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣,乐意为开源社区提供“资源”,那么我建议你设置GPG sign。未来是不可预知的,人人都可能成为巨佬。
使用
因为我只在Mac环境下配置过GPG,Windows只是打游戏用,所以用的少,Linux/类Unix可以参考一下。其它系统等待他人补充......
Mac
Mac默认是不带GPG的,需要通过第三方软件包安装器Homebrew进行安装,首先先安装Homebrew,如已安装可以跳过。
编辑器限制原因不能使用默认标题进行分步了,故使用1、2、3等小数字代替。
安装Homebrew
在安装之前需要从系统信息中查看芯片为Intel/M系列
Intel使用
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
Intel按照脚本提示,选源,输密码,回车一路绿灯就好了,如果这都不会......可能你不是很适合开发,因为该脚本是国内开发者编写的,中文和一键化安装都集齐了。
M系列使用
/bin/zsh -c "$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)"
并且因为M系列系统结构发生改变,包安装位置不在是以前的/usr/local/,而是在/opt/homebrew,所以要将配置文件里的环境变量改过来。
1.首先进入根目录
cd ~
2.创建.zshrc文件
touch .zshrc
3.打开文件进行编辑
open -e .zshrc
4.如果有旧的环境就修改,没有就新增
export PATH="/opt/homebrew/bin:$PATH"
export PATH="/opt/homebrew/sbin:$PATH"
5.保存
使用command + s
6.生效环境变量
source .zshrc
7、测试
brew -v
若终端顺利打印出brew的版本,那么就安装成功了!
注:本人没有使用过M系列设备,该教程在知乎上找到的
使用Homebrew安装GPG
brew install gnupg pinentry-mac
为GPG添加环境变量,否则在签名的时候会发生报错(使用bash请自行替换配置文件)
echo "export GPG_TTY=$(tty)" >> ~/.zshrc
source ~/.zshrc
生成一个GPG keys
gpg --full-generate-key
默认使用的是ECC,我使用的是RSA,按照自己喜好,或从百度搜索非对称和对称加密算法之间的区别,这里只做使用方法的介绍,不做赘述。
然后添写密钥长度和使用有效期,这里建议选择长期,并做备份,一辈子用一个就够了。
个人信息按照Github信息填写,真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码,强烈建设设置一个较为复杂的密码,并牢记,当然也可以不设置。
使用GPG对Git的commit和tag进行签名
先为Git定义GPG二进制所在地
git config --global gpg.program $(which gpg)
查看GPG keys ID
gpg --list-secret-keys --keyid-format=long
如图所示RSA/后面紧跟的一串就是GPG keys ID
git config --global user.signingkey "GPG key ID"
为Git设置全局commit和tag签名
git config --global commit.gpgsign true
git config --global tag.gpgSign true
参见
接下来就可以愉快的编写程序了~
在Github配置GPG keys
在终端输入
gpg --armor --export "GPG key ID"
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----,包含它们都复制下来。
打开Github网页,并登录自己的账号。按照下述操作依次执行。 头像-->Setting-->SSH and GPG keys-->New GPG key,标题自己怎么舒服怎么来,将第一步复制的内容全部粘贴然后保存起来,这样Github就能识别到你commit中包含的GPG sign的信息了,你就可以在commit history或release等页面看到绿色的签名后的标志了。
参考资料:
[1] 百度百科 -- Git:https://baike.baidu.com/item/GIT/12647237?fr=ge_ala
[2] 菜鸟教程 -- Git基本操作:https://www.runoob.com/git/git-basic-operations.html
[3] CSDN -- git merge 使用简介: https://blog.csdn.net/All_In_gzx_cc/article/details/125482617
[3] 知乎 -- MAC 安装 homebrew 国内镜像: https://zhuanlan.zhihu.com/p/547898033
- ↑ 生成这个hash值,它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说,Git使用了sha1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。在Git中,根据commit的sha1值40个十六进制数字进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名