惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
人人都是产品经理
人人都是产品经理
H
Heimdal Security Blog
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
雷峰网
雷峰网
Hacker News: Ask HN
Hacker News: Ask HN
Webroot Blog
Webroot Blog
Microsoft Azure Blog
Microsoft Azure Blog
MyScale Blog
MyScale Blog
A
About on SuperTechFans
V2EX - 技术
V2EX - 技术
小众软件
小众软件
博客园 - Franky
博客园 - 司徒正美
P
Privacy International News Feed
爱范儿
爱范儿
U
Unit 42
博客园 - 叶小钗
The Hacker News
The Hacker News
C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Simon Willison's Weblog
Simon Willison's Weblog
N
News and Events Feed by Topic
D
Docker
T
Threatpost
MongoDB | Blog
MongoDB | Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Help Net Security
L
LINUX DO - 最新话题
Security Latest
Security Latest
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
A
Arctic Wolf
Spread Privacy
Spread Privacy

Jun's Blog

2023 年度总结 OS 学习记 之 XV6 如何编译 GraalVM LLVM 中端优化之 InstCombine C++ 中 inline 关键字的语义 链接与库 C++ 移动语义基础 如何优化矩阵相乘 2022年度总结 CUDA初学笔记 汇编语言之保护模式 汇编语言之实模式 浅析 libc++ 中的 string 实现 std::expected 基本使用 C++模板基础 CSAPP第九章笔记之虚拟内存 CSAPP第八章笔记之异常控制流 2021年度总结 编译安装GCC12 如何给LLVM贡献代码 CSAPP第三章笔记Part 2 CSAPP第三章笔记Part 1 GDB基本使用笔记 读Effetive Modern C++ 之类型推导 给计算机新生的一封信 CMake学习笔记 由Redis学习数据结构--字典 C++中lambda表达式基础 由Redis学习数据结构--链表 对Python及爬虫行业的思考 Vim实用技巧 浅谈C++中的类 简要剖析const关键字 正则表达式基础总结 使用Hugo和Firebase部署个人博客 浅谈HTTPS证书 Linux常用命令总结 Linux下使用v2ray 娱乐至死读书笔记 自控力读书笔记 少有人走的路力读书笔记 Postfix & Dovecot 自建邮箱服务 Linux用户管理 Linux开机流程 Linux文件与目录 Linux硬盘管理 Linux服务浅谈 About Me
Git学习笔记
Jun · 2021-02-28 · via Jun's Blog

· Jun

本文历经几次修改,主要是我对Git的一些学习和理解。其内容主要参考Pro Git。 在经过几次重写后,我决定以问答和解释相结合的形式来总结与Git相关的知识点。

git的基本工作模型

1
2
3
4
5
+--------------+      +--------------+      +----------+
|              |      |              |      |          |
| Working area | ===> | Staging area | ===> | Git repo |
|              |      |              |      |          |
+--------------+      +--------------+      +----------+
  • Working area 所有被Git track过的文件都认为被放到这个区域。
  • Staging area 这里负责存放准备提交的文件。
  • Git repo 这里就是提交后的文件了。

git分支

1
2
3
+-----+    +-----+    +-----+ <---- master   HEAD
|123a |<---|1e69 |<---|5adc | ^               |
+-----+    +-----+    +-----+ |_______________+

在Git中,分支可以认为是指向一个commit的指针,其中HEAD永远指向当前所在的commit。

怎么将文件加入staging area?

如果是提交单个文件, 可以使用git add <filename>,如果是提交多个文件,可以使用git add .git add *.c等。如果想将一个文件中的多个修改分开提交,可以使用git add -p

怎么将加入staging area的文件退回工作区?

如果错误使用git add .将一些不想要的文件加入了staging area, 可以使用git restore --staged <filename> 将文件退回工作区,并保留了更改。

怎么撤销当前的提交并保留修改?

假如我们刚写好一个patch并想要写下一个,但是忘记切回主分支而是直接切了一个新分支,这就导致了新分支的base branch错了。我们可以先撤销掉当前的提交:

接着我们再切一个新的分支提交就好了:

1
2
git checkout -b new-branch
git commit -a

怎么修改之前的commit?

假如你对上一个commit不满意,比如少提交了文件,写错了commit message等,你可以:

那怎么修改非上一个commit呢?

如果你想修改非上一个commit的话,就需要使用rebase了。

假设我们有如下的git历史:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
+----------+
| commit 3 |
+----------+
     ||
	 \/
+----------+
| commit 2 |
+----------+
     ||
	 \/
+----------+
| commit 1 |
+----------+

我们想修改commit 2的提交信息的话,可以:

接着找到我们想修改的提交,将其pick改成edit,并保存退出。

这时候我们就可以使用git commit --amend来修改了,最后git rebase --continue就可以了。

怎么将放弃工作区的修改?

对于处于工作区的修改,可以使用git restore <filename> 丢弃修改。

注意此操作不能撤销,修改的文件将直接丢失!

怎么查看git历史?

1
2
3
git log #默认的查看历史
git log --pretty=oneline #以单行的形式查看历史
git log --author="Jun Zhang" #搜索指定作者的commits

如何将多个commits合并成一个?

假设我们有git历史如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
commit 4ab5de2355dc7f910ed39d1b71052fc1d30a0da3 (HEAD -> master)
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:27:02 2021 +0800

    finally fix up

commit 2d187de6e426e754084663a1710de9fd7a87c871
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:26:25 2021 +0800

    another fix up

commit ca0fe9c9c1f116cf83905aaacc0736359af3fb7e
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:26:03 2021 +0800

    fix up

commit 418809d837801cc8b2816567b373747599730736
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:25:41 2021 +0800

    Initial commit

我们想把前三个commit合并成一个,因为他们是相关联的。我们可以这么做:

git会展示如下内容:

1
2
3
4
pick ca0fe9c fix up
pick 2d187de another fix up
pick 4ab5de2 finally fix up
# Rebase 418809d..4ab5de2 onto 418809d (3 commands)

可以看到这里的历史与git log展示的历史顺序刚好相反。我们要把下面两个后来的commits 合并到之前的那一个上,我们可以:

1
2
3
pick ca0fe9c fix up
squash 2d187de another fix up
squash 4ab5de2 finally fix up

保存后git便会要求我们重写git commit messge,此后使用git log可以看到3个commits被合并成了一个。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
commit fedae1c1c4265c314166729c16a2855dfddc1f3c (HEAD -> master)
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:26:03 2021 +0800

    squash 3 commits into one.

commit 418809d837801cc8b2816567b373747599730736
Author: Jun Zhang <jun@junz.org>
Date:   Fri Dec 24 22:25:41 2021 +0800

    Initial commit

怎么在切换分支的时候暂时保存工作进度?

有时候在一个分支还没有工作完,我们并不想commit,但是因为一些原因我们又需要切一个新的分支, 这时候便可以使用git stash这个命令。

比如我们现在在分支dev上,我们有一些在staging area的文件,而我们并不想立刻commit。我们可以 使用git stash暂存更改。git stash会把更改放到一个栈型的结构中,后面我们可以继续使用git stash 暂存更改。

使用git stash list来查看所有暂存的更改,据个例子:

1
2
stash@{0}: WIP on master: fedae1c squash 3 commits into one.
stash@{1}: WIP on dev: fedae1c squash 3 commits into one.

我们分别在dev分支和master分支上使用了git stash,可以看到我们有两个暂存的更改。

当我们准备好时,可以使用git stash apply stash@{n}来释放之前暂存的修改。如果直接使用git stash apply, 会应用栈顶的那个更改。但是注意应用后在栈中存放的更改并不会丢失,而是继续存放在那除非手动使用git stash drop stash@{n}。 也可以使用git stash pop应用栈顶的那个更改并自动将其drop掉。

怎么合并分支?

合并分支有两种策略,一种是默认的git merge,另一种是git rebase

1
2
3
4
5
6
7
                      +-----+
              +-------|9e7d |(dev)
              |       +-----+
             \/
+-----+    +-----+    +-----+
|123a |<---|1e69 |<---|5adc |(master)
+-----+    +-----+    +-----+

对于merge来说,其工作原理是由其公共commit后diff创建一个新的commit。即它会合并9e7d5adc,并 加到5adc上。

而对于rebase来说,其工作原理是将新的commit移动到其他分支上,像是改变了其parent。

1
2
3
4
5
git checkout -b dev
# make some changes
git rebase master
git checkout master
git merge dev

如果说在开发过程中远程master分支有了新的commit,如上图的5adc,我们应该先:

1
2
git checkout master
git pull

在此之后再使用rebase