Git使用教程:修订间差异

来自Uotan Wiki · 刷机百科
→‎git push
 
(未显示4个用户的28个中间版本)
第17行: 第17行:
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。


<code>git config --global user.name "your username"</code><code>git config --global user.email "your email"</code>  
<code>git config --global user.name "your username"</code>
 
<code>git config --global user.email "your email"</code>
 
 
更改默认编辑器
 
<code>git config --global core.editor nano</code>


==== git clone ====
==== git clone ====
用于将远程仓库的代码克隆到本地
用于将远程仓库的代码克隆到本地,以下是命令中各个参数的含义:


<code><url></code>
<code><url></code>
第34行: 第41行:
克隆指定分支下的仓库内容
克隆指定分支下的仓库内容


==== git add ====
例如我们要克隆<code>LineageOS</code>的内核源码,指定<code>lineage-21</code>分支,且仅保留最近一个提交,则需要输入:
添加某个文件,或者目录到暂存区,用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中


<code>git clone -b lineage-21 <nowiki>https://github.com/LineageOS/android_kernel_xiaomi_sdm845</nowiki> --depth=1</code>


添加一个或者多个文件到暂存区之中
==== git add ====
添加某个文件,或者目录到暂存区,用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中


<code>git add [file1] [file2]</code>
<code>git add [file1] [file2]</code>


添加指定目录(文件)到暂存区,包括子目录:
添加指定目录(文件)到暂存区,包括子目录:
添加当前目录下的所有文件到暂存区,包括子目录:


<code>git add [dir]</code>
<code>git add [dir]</code>
第54行: 第60行:
==== git status ====
==== git status ====
查看当前仓库的状态,此时git会在你的终端输出以下内容
查看当前仓库的状态,此时git会在你的终端输出以下内容
<p><em style="color: gray;">此处演示为英文,如果您的git终端输出为中文也是同理的</em></p>
<pre>
On branch master
No commits yet
Changes to be committed:  


(此处演示为英文,如果您的git终端输出为中文也是同理的)
(use “git rm --cached <file>...” to unstage)       
new file:   makefile
</pre>


<code>On branch master</code>  
输出内容分别为
<pre>
您目前所在的分支
目前的提交
需要更改的内容
新增的文件
修改的文件
删除的文件
</pre>


<code>No commits yet</code>
==== git commit ====
用于将暂存区我们保存的更改文件添加到本地仓库,并且会生成一条提交(commit)
 
提交暂存区的更改到本地仓库


<code>Changes to be committed:  </code>
git commit


<code>(use “git rm --cached <file>...” to unstage)       </code>
这一操作将会打开 git 的默认的文本编辑器,你应该在这里写明 commit message. 第一行是标题,下面的都是解释说明,前面带有#的行不会被列入文本中.


<code>new file:   makefile</code>
好的 commit message 是方便所有人的举措. 对初学者来说,不要求做的多么规范,但是建议做到以下几点:


输出内容分别为
- 简短说明本次 commit 做了什么,至少你自己看一眼能知道自己在干什么


* 您目前所在的分支
- 尽力做到一个 commit 一个修改,尽量不要大杂烩或者一个修改拖好几个 commit
* 目前的提交
* 需要更改的内容
* 新增文件
* 修改文件
* 删除文件


==== git commit ====
- 如果是比较大的项目(例如 Android Kernel),尽量写明你所修改的模块,令人一目了然. 例如:
用于将暂存区我们保存的更改文件添加到本地仓库,并且会生成一条提交(commit)


提交暂存区的更改到本地仓库
<code>ARM64: configs: enchilada: Disable virtual terminal</code>


<code>git commit -m "message"</code>
您必须注意:


[注] message 可以是你的备注信息
- 如果这个提交是别人的,必须用<code>--author="ExampleName <example@example.com>"</code>参数说明这是哪位作者的提交. 这是对他人思考和试验成果的尊重.


提交暂存区中的指定文件到本地仓库
- Commit message 里不得谩骂他人,不要带有其他人或者你自己的无关私人信息.


如果你没有使用上述<code>git add</code>命令暂存你的修改文件,可以使用


<code>git commit -a</code>
如果想要直接提交而不添加暂存区(偷懒),可以指定<code>-a</code>参数.


进行直接提交
您也可以使用<code>-m "example commit message"</code>来直接 commit.


==== git checkout ====
==== git checkout ====
第103行: 第121行:
<code>git checkout <branch-name></code>
<code>git checkout <branch-name></code>


例如在您的仓库中有这几个分支:<code>-> master</code>
例如在您的仓库中有这几个分支:
 
<pre>
<code>test</code>
-> master (Default)
 
  backup
  test
</pre>
您当前处于 master 分支,如果想要切换到test分支,我们可以使用
您当前处于 master 分支,如果想要切换到test分支,我们可以使用


第115行: 第135行:


<code>git checkout -- <file></code>
<code>git checkout -- <file></code>
==== git push ====
==== git push ====
用于将本地的分支版本上传到远程仓库并进行合并
用于将本地的分支版本上传到远程仓库并进行合并
第138行: 第159行:
<code>git push --force origin master</code>
<code>git push --force origin master</code>


--force 此处可以直接简单化为 -f  
--force 此处可以直接简单化为 -f . 强烈建议使用 --force-with-lease参数,更为安全.


如果你想要删除主机内的某个分支,你可以使用--delete参数
如果你想要删除主机内的某个分支,你可以使用--delete参数
第145行: 第166行:


==== git diff ====
==== git diff ====
用于比较当前工作区与上一个版本之间的差异
用于比较当前工作区与上一个版本之间的差异<pre>
diff --git a/example b/example
 
index fbb8c85..d65c7eb 100644
 
--- a/example
 
+++ b/example
 
@@ -1 +1,2 @@
 
114514
 
+1919180
</pre>


==== git log ====
==== git log ====
第163行: 第198行:


这些输出分别为
这些输出分别为
 
<pre>
* <strong>commit sha1 hash</strong>: 针对你这个提交的commit id
commit sha1 hash:   针对你这个提交的 commit id
 
Author: commit     作者名称   <you@example.com>
* <strong>Author</strong>: commit 作者名称 <you@example.com>
Date: commit       日期
* <strong>Date</strong>: commit 日期
commit:            名称
* <strong>commit</strong>: 名称
</pre>
*
*
*


关于sha1_hash的介绍请看这里<ref>生成这个hash值,它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说,Git使用了sha1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。在Git中,根据commit的sha1值40个十六进制数字进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名</ref>
关于sha1_hash的介绍请看这里<ref>生成这个hash值,它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说,Git使用了sha1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。在Git中,根据commit的sha1值40个十六进制数字进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名</ref>
第180行: 第212行:


例如
例如
 
<pre>
347595d (HEAD -> master) modify makefile
347595d (HEAD -> master) modify makefile


3a5b0d1 initial commit: add makefile
3a5b0d1 initial commit: add makefile
</pre>


*
==== git cherry-pick ====
 
 
cherry-pick (遴选) 和它的名称一样,挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改,移植到当前的分支。
 
如果我们想在我们正在开发的版本上,添加一个其他版本中的功能代码。就可以使用 cherry-pick ,将这个功能相关的 commit 提取出来,合入该版本。
 
<code>git cherry-pick <commit-id></code>
 
 
当我们执行完 <code>cherry-pick</code>操作之后,会自动生成一个<code>commit</code>以及对应新的<code>commit-id</code>
 
在顺利的情况下我们可以直接通过,但如果遇到代码等因为变量名,写法等不同的情况,<code>cherry-pick</code>大概率会报错,此时我们需要进行报错处理。
 
第一种方案是手动修改
 
我们可以先使用<code>git status</code>检查当前遴选时冲突的文件
 
然后 <code>git checkout --ours filename</code>
 
然后按照提交的修改内容进行手动修改
 
随后使用<code>git add</code>命令将文件重新加入暂存区
 
再使用
 
<code>git cherry-pick --continue</code>
 
命令让 cherrypick 操作继续执行。
 
第二种方案是直接退出<code>cherry-pick</code>进程,一般适用于冲突文件实在太多了难以按照方案一处理的情况。
 
需要注意的是,如果您当前正在遴选的提交在该分支已经存在也会冲突,在这种情况下,您需要解决冲突并手动解决问题。
 
<code>git cherry-pick --abort</code>
 
==== git fetch ====
git fetch 命令用于从远程获取仓库。
 
==== git merge ====
<code>git merge</code>是用来把分叉的提交历史放回到一起(合并)的方式。
 
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。
 
 
==== git pull ====
用于从远程获取代码并合并本地的版本。
 
<code>git pull</code>其实就是<code>git fetch</code>和<code>git merge FETCH_HEAD</code> 的简写。
 
格式如下:
 
<code>git pull <remote-host-name> <remote-branch-name>:<local-branch-name></code>
 
==== git rebase ====
用于需要修改历史上某一项commit
 
<code>git rebase -i HEAD~<commit number></code>
 
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器,若未配置则是默认,vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。
有以下操作:
 
1.edit,顾名思义编辑此commit,替换完保存后请修改内容,使用<code>git add</code>或vscode,github desktop将修改文件添加到暂存区,之后命令行执行<code>git commit --amend</code>这样commit就修改成了
 
2.squash,合并几个提交,确认一个父提交,将要合并的commit,从下向上替换字符串,会从下向上合并(方位指的是<code>git rebase</code>后弹出的编辑器)
 
3.drop,需要移除的commit
 
4.reword,修改commit信息
 
另外,还可以使用首字母来说明命令。
 
==== git subtree ====
子树,在Android开发中多用于Kernel侧更改,如跟踪audio模块等
 
<code>git subtree add --prefix=<目录> <仓库地址> <远程分支></code>
 
如果需要更新远程库时
 
<code>git subtree pull --prefix=<目录> <仓库地址> <远程分支></code>
 
==== git submodule ====
 
===== 子模块功能的概述 =====
<code>git submodule</code>允许在自己的Github仓库里加入别人的github仓库,作为自己仓库的子仓库(即submodule)。
 
为什么我们会需要使用子模块?当我们维护一个项目时有可能遇到以下情况,例如维护某款机型的KernelSU内核,我们需要将KernelSU导入至我们的内核源码中,如果我们直接clone进去容易带来一个问题,如果KernelSU更新了怎么办?此时我们便可以使用子模块来解决这个问题
 
<code>git submodule</code>允许在git仓库里存放别人仓库的url,作为自己的子模块,其核心内容是在Git仓库里面加入一个<code>.gitmodules</code>文件,里面会记录各个submodule的名字,路径,以及对应链接。
 
===== 加入子模块 =====
<code>git submodule add <url> <path></code>
 
此时 <code>.gitmodules</code>内会自动生成以下内容
 
[submodule "xxx"]
 
path = xxx
 
url = xxx
 
===== 初始化子模块 =====
<code>git submodule init</code>
 
===== 更新子模块 =====
<code>git submodule update</code>
 
=== Git进阶 ===
 
==== GPG key ====
 
===== 简介 =====
平时在Github上摸鱼的时候,是不是经常能看见如下图所示,有一个绿色的"Verified"字样,看着很酷,实际上这是为了确保commit为开发者本人所写的进行的GPG签名。
[[文件:Github GPG sign.png|居中]]
因为Git的默认机制,任何人都可以通过你的邮箱和用户名创建虚假的commit,甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣,乐意为开源社区提供“资源”,那么我建议你设置GPG sign。未来是不可预知的,人人都可能成为巨佬。
 
===== 使用 =====
因为我只在Mac环境下配置过GPG,Windows只是打游戏用,所以用的少,Linux/类Unix可以参考一下。其它系统等待他人补充......
 
====== Mac ======
Mac默认是不带GPG的,需要通过第三方软件包安装器Homebrew进行安装,首先先安装Homebrew,如已安装可以跳过。
 
编辑器限制原因不能使用默认标题进行分步了,故使用1、2、3等小数字代替。
 
安装Homebrew
 
在安装之前需要从系统信息中查看芯片为Intel/M系列
 
Intel使用
 
<code>/bin/zsh -c "$(curl -fsSL <nowiki>https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh</nowiki>)"</code>
 
Intel按照脚本提示,选源,输密码,回车一路绿灯就好了,如果这都不会......可能你不是很适合开发,因为该脚本是国内开发者编写的,中文和一键化安装都集齐了。
 
M系列使用
 
<code>/bin/zsh -c "$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)"</code>
 
并且因为M系列系统结构发生改变,包安装位置不在是以前的/usr/local/,而是在/opt/homebrew,所以要将配置文件里的环境变量改过来。
 
1.首先进入根目录
 
<code>cd ~</code>
 
2.创建.zshrc文件
 
<code>touch .zshrc</code>
 
3.打开文件进行编辑
 
<code>open -e .zshrc</code>
 
4.如果有旧的环境就修改,没有就新增
 
<code>export PATH="/opt/homebrew/bin:$PATH"
 
export PATH="/opt/homebrew/sbin:$PATH"</code>
 
5.保存
 
使用command + s
 
6.生效环境变量
 
<code>source .zshrc</code>
 
7、测试
 
<code>brew -v</code>
 
若终端顺利打印出brew的版本,那么就安装成功了!
 
注:本人没有使用过M系列设备,该教程在知乎上找到的
 
使用Homebrew安装GPG
 
<code>brew install gnupg pinentry-mac</code>
 
[[文件:截屏2024-02-17 17.34.48.png|居中]]
 
为GPG添加环境变量,否则在签名的时候会发生报错(使用bash请自行替换配置文件)
 
<code>echo "export GPG_TTY=$(tty)" >> ~/.zshrc
source ~/.zshrc
</code>
 
生成一个GPG keys
 
<code>gpg --full-generate-key</code>
 
[[文件:截屏2024-02-17 17.45.51.png|居中]]
 
默认使用的是ECC,我使用的是RSA,按照自己喜好,或从百度搜索非对称和对称加密算法之间的区别,这里只做使用方法的介绍,不做赘述。
 
然后添写密钥长度和使用有效期,这里建议选择长期,并做备份,一辈子用一个就够了。
 
[[文件:截屏2024-02-17 17.46.06.png|居中]]
[[文件:截屏2024-02-17 17.46.35.png|居中]]
 
个人信息按照Github信息填写,真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码,强烈建设设置一个较为复杂的密码,并牢记,当然也可以不设置。
 
使用GPG对Git的commit和tag进行签名
 
先为Git定义GPG二进制所在地
 
<code>git config --global gpg.program $(which gpg)</code>
 
查看GPG keys ID
 
<code>gpg --list-secret-keys --keyid-format=long</code>
 
如图所示RSA/后面紧跟的一串就是GPG keys ID
[[文件:截屏2024-02-17 17.57.01.png|居中]]
<code>git config --global user.signingkey "GPG key ID"</code>
 
为Git设置全局commit和tag签名
 
<code>git config --global commit.gpgsign true
 
git config --global tag.gpgSign true</code>
 
参见本文“在Github配置GPG keys”部分开启下一步操作
 
接下来就可以愉快的编写程序了~
 
======在Github配置GPG keys======
在终端输入
 
<code>gpg --armor --export "GPG key ID"</code>
 
将输出的内容从-----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等页面看到绿色的签名后的标志了。
 
==== SSH key ====
可以通过生成SSH key,并保存在Github等托管平台上实现免密Push,这也是官方推荐的方法,过去输入用户名/密码的方式早已被抛弃。
 
===== 生成Key =====
1.打开终端并输入
 
<code>ls ~/.ssh</code>
 
检查是否已经存在了SSH密钥。如果你看到包含id_rsa等文件,说明你已经有了SSH key,可以跳过第 2 步和第 3 步。
 
2.输入,生成新的SSH密钥。你可以直接按回车键使用默认的文件路径和空密码,也可以自己设置。
 
<code>ssh-keygen -t rsa -b 4096 -C "your_email@example.com"</code>
 
4.在终端输入或使用文本编辑器打开,并复制所有内容
 
<code>vim ~/.ssh/id_rsa.pub</code>
 
5.打开Github网页,并登录自己的账号。按照下述操作依次执行。
 
头像-->Setting-->SSH and GPG keys-->New SSH key
 
自己起个标题名并粘贴4步中所有内容,保存,接下来你可以免密对Github上的repo进行操作了。


==== 参考资料: ====
==== 参考资料: ====
[1] 百度百科-- Git:<nowiki>https://baike.baidu.com/item/GIT/12647237?fr=ge_ala</nowiki>
[1] 百度百科 -- Git:<nowiki>https://baike.baidu.com/item/GIT/12647237?fr=ge_ala</nowiki>
 
[2] 菜鸟教程 -- Git基本操作:<nowiki>https://www.runoob.com/git/git-basic-operations.html</nowiki>
 
[3] CSDN -- git merge 使用简介: <nowiki>https://blog.csdn.net/All_In_gzx_cc/article/details/125482617</nowiki>
 
[4] 知乎 -- MAC 安装 homebrew 国内镜像: <nowiki>https://zhuanlan.zhihu.com/p/547898033</nowiki>
 
[5] Github -- Generating a new GPG key: <nowiki>https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key</nowiki>
 
[6] Github -- Adding a GPG key to your GitHub account: <nowiki>https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account</nowiki>
 
[7] Github -- Generating a new SSH key and adding it to the ssh-agent: <nowiki>https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent</nowiki>


[2] 菜鸟教程-- Git基本操作:<nowiki>https://www.runoob.com/git/git-basic-operations.html</nowiki>
[8] Github -- Adding a new SSH key to your GitHub account: <nowiki>https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account</nowiki>

2024年8月25日 (日) 11:09的最新版本

Git的由来:

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理,也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。

常见的代码托管平台:

Github

Gitlab

Gitee

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

这一操作将会打开 git 的默认的文本编辑器,你应该在这里写明 commit message. 第一行是标题,下面的都是解释说明,前面带有#的行不会被列入文本中.

好的 commit message 是方便所有人的举措. 对初学者来说,不要求做的多么规范,但是建议做到以下几点:

- 简短说明本次 commit 做了什么,至少你自己看一眼能知道自己在干什么

- 尽力做到一个 commit 一个修改,尽量不要大杂烩或者一个修改拖好几个 commit

- 如果是比较大的项目(例如 Android Kernel),尽量写明你所修改的模块,令人一目了然. 例如:

ARM64: configs: enchilada: Disable virtual terminal


您必须注意:

- 如果这个提交是别人的,必须用--author="ExampleName <example@example.com>"参数说明这是哪位作者的提交. 这是对他人思考和试验成果的尊重.

- Commit message 里不得谩骂他人,不要带有其他人或者你自己的无关私人信息.


如果想要直接提交而不添加暂存区(偷懒),可以指定-a参数.

您也可以使用-m "example commit message"来直接 commit.

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 . 强烈建议使用 --force-with-lease参数,更为安全.

如果你想要删除主机内的某个分支,你可以使用--delete参数

git push origin --delete <branch-name>

git diff

用于比较当前工作区与上一个版本之间的差异

diff --git a/example b/example

index fbb8c85..d65c7eb 100644

--- a/example

+++ b/example

@@ -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 fetchgit 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

4.reword,修改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”部分开启下一步操作

接下来就可以愉快的编写程序了~

在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等页面看到绿色的签名后的标志了。

SSH key

可以通过生成SSH key,并保存在Github等托管平台上实现免密Push,这也是官方推荐的方法,过去输入用户名/密码的方式早已被抛弃。

生成Key

1.打开终端并输入

ls ~/.ssh

检查是否已经存在了SSH密钥。如果你看到包含id_rsa等文件,说明你已经有了SSH key,可以跳过第 2 步和第 3 步。

2.输入,生成新的SSH密钥。你可以直接按回车键使用默认的文件路径和空密码,也可以自己设置。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

4.在终端输入或使用文本编辑器打开,并复制所有内容

vim ~/.ssh/id_rsa.pub

5.打开Github网页,并登录自己的账号。按照下述操作依次执行。

头像-->Setting-->SSH and GPG keys-->New SSH key

自己起个标题名并粘贴4步中所有内容,保存,接下来你可以免密对Github上的repo进行操作了。

参考资料:

[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

[4] 知乎 -- MAC 安装 homebrew 国内镜像: https://zhuanlan.zhihu.com/p/547898033

[5] Github -- Generating a new GPG key: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key

[6] Github -- Adding a GPG key to your GitHub account: https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account

[7] Github -- Generating a new SSH key and adding it to the ssh-agent: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

[8] Github -- Adding a new SSH key to your GitHub account: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account

  1. 生成这个hash值,它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说,Git使用了sha1并非是为了安全性,而是为了数据的完整性;它可以保证,在很多年后,你重新checkout某个commit时,一定是它多年前的当时的状态,完全一摸一样,完全值得信任。在Git中,根据commit的sha1值40个十六进制数字进行了简单的划分目录,以前2位数字作为目录名,其下面是剩余38位数字组成的一个文件名