git学习笔记

2021-11-03 10:27:18 digiproto

01

git和svn的区别


1.git是分布式的,而svn是非分布式的。


2.git绝大多数操作都是本地化的,不需要网络。比方说查看提交历史。


3.git只会添加数据,不会删除数据,所以git几乎没有可能导致文件无法恢复的操作


4.存储方式:

(1) svn:按文件变更列表的方式存储消息。既即一组基本文件和每个文件随时间逐步累积的差异(它们通常称作 基于差异(delta-based) 的版本控制),也就是说 vVersion 2 中记录的不是修改过后完整的 Ffile A,而是 Ffile A 修改的部分,在 Vversion 2 中要得到完整的 Ffile A,则需要 Vversion 1.Ffile A + Vversion 2.△1才可以。  

图片关键词


(2) git:git 会在每次提交的时候将变更的文件直接拷贝形成一个 blob 对象,而不是和上一个版本的 diff。为了效率,如果文件没有修改,git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 git 对待数据更像是一个快照流。

图片关键词


02

工作区、暂存区、版本库:


1.各个区详解:

(1) 工作目录(Working Directory):就存放代码的地方,在这个文件夹下有一个 .git 文件,该文件存储的就是 git 的所有数据,包括 暂存区、资源库。

(2) 暂存区(Stage/Index):存放的是已暂存的内容。

(3) 本地资源库(Repository或Git Directory):存放的是已暂存的内容、已commit文件。

(4) 远程git仓库(Remote Directory):远程仓库、即已push文件。


2.关系图:

图片关键词


3. 文件的四种状态:


(1) 注意:

① 这里的四种状态都不涉及到远程仓库,最后一步的已提交也只是到达本地仓库。

② 已暂存、已修改、已提交这三种都是已跟踪。

③ 已修改和已暂存都位于暂存区。


(2) 四种状态详解:

① 未跟踪(Untracked):未跟踪,此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged。

② 已暂存(Staged):位于暂存区,如果该文件被修改就会变成已修改。

③ 已修改(Modified):位于暂存区后被修改但还没到资源库,也就是已经 git add 但还没有 git commit。

④ 已提交(committed):即已经安全到达本地库中。


(3) 文件四种状态和git三个区的位置图:

① 说明:

1) 工作目录下有一个 .git 文件夹,该文件夹下包含着所有 git 消息(所以该文件千万不要乱动)。

2) 未暂存的文件只会位于工作目录,而不会存在于.git下。

3) 已暂存和已提交都位于暂存区中。

图:

图片关键词


(4) 转换关系:

① 引起文件的状态发生变化的几点原因举例:

1) 新增文件:这个会将文件状态变成未跟踪(Untracked files)。

2) 修改文件:这个会将文件状态变成已修改(Changes not staged for commit)。

3) 删除文件:这个会将文件状态变成已修改(Changes not staged for commit)。


② 图的几点说明:

1) 该图是引起文件转变的几点原因(但不是全部,详情见第三章)。

2) 下图就是通过不同 git 命令在让文件在不同状态之间来回切换的方式。

3) 对于新增文件而言而已,状态只有已提交、已暂存、未跟踪;而对于修改、删除文件而言,其状态只有已提交、已暂存、已修改。

4) 对于新增文件,无论里面有没有内容,一旦 git add 后就会变成已暂存,而如果在变成已暂存再对其进行修改,则该文件会同时存在于已暂存和已修改。

图:

图片关键词


03

能改变文件状态的命令:


1. add:

(1) 说明:

① 将文件从已修改、未跟踪变成已暂存。

(2) git add .:添加所有文件和文件夹。

(3) git add xxx-1.txt xxx-2.txt xxx-3:添加指定文件或文件夹。


2. reset HEAD(reset XXX):

(1) 说明:

① reset 用于重置当前分支的 HEAD 指向(它不会切换分支,是在同一个分支中移动指向)。

(2) 大致流程:

① 修改前:

图片关键词


② 执行一次 git reset HEAD~1:HEAD~1 表示当前指向的前一次提交,所以这里就变成了C2。

图片关键词


③ 再执行一次 git reset HEAD~1:

图片关键词


④ 执行 git reset C4:reset 是重置,可以往前退,也可以往后进。

图片关键词


(3) 四种模式:


① 说明:

1) 上面的流程只是为了让我们能更好的入门 reset ,但实际上 reset 有四种模式,情况要比上图中要复杂的多。

2) 我们之前学习到的 git 一共有三个区域:本地资源库、暂存区、工作区。而 reset 四种模式就是影响的区域不同。


② git reset --soft:


1) 说明:

a. 这个只会影响本地资源库,但暂存区和工作目录的没有任何变化。

b.对于新增文件:file4.txt 是 C2 中新增的(C1 中没有 file4.txt)。此时执行 reset —soft HEAD~1,由于工作目录没移动指针,所以该文件仍然是存在于工作目录中的(即仍然存在于硬盘); 而由于暂存区没有改动,所以 file4.txt 仍然是在暂存区的,但是由于资源库的回退了,所以该文件就变成已暂存了。

图片关键词


c.对于修改文件: file4.txt 在 C2 中做了修改(C1 中也有 file4.txt )。此时执行 reset —soft HEAD~1,由于工作目录没移动指针,所以该文件仍然是存在于工作目录中的(即仍然存在于硬盘);而由于暂存区没有改动,所以暂存区的内容就和工作区的内容有偏差了,所以此时会显示有数据未提交(即处于已暂存),但和上面的差别是上面的是 new file,这里是modified。

图片关键词


2) 图:

a.修改前:

图片关键词


b.执行 git reset --soft C1:

图片关键词


③ git reset [--mixed]:


1) 说明:

a. 这个只会影响本地资源库和暂存区,但工作目录的没有任何变化。

b.对于新增文件:file4.txt 是 C2 中新增的(C1 中没有 file4.txt)。此时执行 reset —soft HEAD~1,由于工作目录没移动指针,所以该文件仍然是存在于工作目录中的(即仍然存在于硬盘);但暂存区和本地资源都发生了改变,所以暂存区和本地资源库是一致的,都不存在该文件,而工作区仍然存在该文件,所以处于未跟踪状态。

图片关键词


c.对于修改文件: file4.txt 在 C2 中做了修改(C1 中也有 file4.txt )。此时执行 reset —soft HEAD~1,由于工作目录没移动指针,所以该文件仍然是存在于工作目录中的(即仍然存在于硬盘);但暂存区和本地资源都发生了改变,所以暂存区和本地资源库是一致的,该文件在 C1 时是处于已提交状态,但执行 reset 由于不会修改工作目录,所以相当于是对已提交文件做了修改,所以是已修改状态。

图片关键词


2) 图:

a.修改前:

图片关键词


b.执行 git reset --soft C1:

图片关键词


④ git reset --hard:


1) 说明:

a. 该模式会影响本地资源库、暂存区和工作区。

b. 由于该模式会冲掉工作区代码,所以如果工作区有未提交的代码,则会导致代码找不到从而导致严重的问题。

2) 图:

a.修改前:

图片关键词


b.执行 git reset —hard C1:

图片关键词


⑤ git reset --merge:


1) 将目标 commit-id 和当前在工作区的文本做比较,如果存在差异则需要保留两者。

2) 在 --hard 模型中,由于它会直接重置暂存区和工作区,所以如果你当前还没有提交的内容时则会被全部冲掉,这个非常危险,而  --merge  能让你保留当前未提交的和目标提交之间的区别,这个比 --hard 安全的多。


(4) 操作某个文件或全部:

① git reset HEAD~1:影响的是全部文件和目录。

② git reset HEAD~1 file.txt:影响的只有该文件或目录(需要特别注意的是对于 --hard 模式只能操作全部,无法操作部分)。


(5) reset 后再提交:

① 说明:相当于开了一个分支。

② 流程:

1) 修改前:

图片关键词


2) reset 后:

图片关键词


3) 修改文件后提交:

图片关键词


(6) 注意:

① 如果我们用 reset 移动过后,需要看全部提交,可以使用 git log --pretty=oneline --all。

② 当我们使用 reset 后,资源库里的提交是一个没少,只不过是我们 HEAD 指向发生了变化而已。

③ 使用 git reset --hard 需要非常小心,如果你在没有提交的情况下使用该命令,将无法再找回这些没有提交的内容。

④ 缺省模式能操作全部和部分(某文件或某目录),但 --soft、—hard、--merge 只能操作全部,无法操作部分。


3. commit:

(1) 说明:

① 提交代码,将暂存区的内容提交到本地资源库,但是这里的本地资源库是指本地,和远程资源库无关。


(2) 命令:

① git commit -m ‘xxx’:将已暂存的内容提交到本地资源库。


② git commit -a -m ‘xxx’:将已修改和已暂存的内容直接提交到已提交,但需要注意的是,该命令无法让未跟踪的文件直接变成已提交。


③ git commit --amend:

1) 说明:

a. 该命令可以修改上一次提交消息或将本次提交追加到上一次提交中。

b. 当执行 git commit --amend 后会出现一个 vi 窗口,你需要进行 vi 编写。


④ 案例:

1) 说明:

a. 实际上是相当于把之前的哪次提交冲掉。


⑤ 流程:

1) 追加前:

图片关键词

2) 追加后:

图片关键词


⑥ 流程示意图:

1) 追加前:

图片关键词


2) 追加后:

图片关键词


4. checkout:

(1) 说明:

① 检出,它和 reset 一样,其本质都是移动 HEAD。


(2) 应用场景:

① git checkout:用于切换分支,即将 HEAD 指向另外一个分支,并重置本地资源库、暂存区和工作区。

② git checkout  :

1) 使得指定文件移动指向。

2) checkout 不会影响本地资源库的指向,它改的是 暂存区和工作目录,并且会完成冲掉工作目录的代码,这个和 git reset --hard 非常像,但 hard 同时还会重置本地资源库的指向。

图片关键词


5. rm:

(1) 说明:

① git 中,文件可能存在于本地资源库或暂存区或工作区。

② 从暂存区和工作区中将文件删除,但不会影响本地资源库。


(2) 命令:

① git rm:

1) 这个命令,只对已提交的文件起作用,其他状态文件无法生效。

2) 如果某个文件同时存在于本地资源库、暂存区和工作区。执行 rm 会将其从暂存区和工作区同时删除(如果你手欠,手动从工作区删除再执行 rm 效果也一样),但不会从本地资源库中删除,而且该文件状态会变成已暂存,此时执行 git commit -m ‘x’ 进行提交,则会让本地资源库的文件也被删除。

② git rm -f:

1) 强制删除,对已提交、已暂存、已修改的起作用,对未跟踪无效。

2) 删除后,如果该文件之前存在于本地资源库则还需要执行 commit。

③ git rm --cache:

1) 只是从暂存区中移除。

2) 该命令对已提交、已暂存、已修改的起作用,对未跟踪无效。

3) 如果某个文件同时存在于本地资源库、暂存区和工作区,本地资源库来说是处于已暂存;对于工作区来说实未跟踪。

图片关键词

④ git rm –r *:递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件。


6. git fetch:

(1) git fetch <远程主机名> <分支名>:

① 如git fetch origin、git fetch origin master-1。

② 将远程仓库的更新全部更新到本地资源库,如图

图片关键词


04

用于解决冲突的命令


1. 产生代码冲突的原因:

(1) 简单来说就是本地修改的文件和目标远程库的同一个文件都有修改。这时无论是pull丶push丶merge时都会产生冲突,但merge命令会帮我们自动把那些可以处理的冲突解决掉,当git无法解决时则需要我们手动解决。


2. diff:

(1) 说明:

① git diff用来比较文件之间的不同。


(2) 命令:

① git diff <分支名1> <分支名2> :比较两个分支上最后 commit 的内容的差别。

② git diff:比较两次提交之间的差异。

③ git diff:当工作区有改动,临时区为空,diff的对比是“工作区与最后一次commit提交的仓库的共同文件”;当工作区有改动,临时区不为空,diff对比的是“工作区与暂存区的共同文件”。

④ git diff --cached 或 git diff --staged:显示暂存区(已add但未commit文件)和最后一次commit(HEAD)之间的所有不相同文件的增删改(git diff --cached和git diff –staged相同作用)。

⑤ git diff HEAD:显示工作目录(已track但未add文件)和暂存区(已add但未commit文件)与最后一次commit之间的的所有不相同文件的增删改。


3. rebase:

(1) 说明:变基,git rebase 用于把一个分支的修改合并到当前分支。


(2) 流程:

① 没有产生冲突的情况下:

修改前:

图片关键词


3) 在 master 分支执行 git rebase fox:

a. 将当前分支和目标分支之间的分叉产生副本,并添加到目标分支后面,并移动 HEAD。

b. 但此时你执行 git push 是会报错的,报错的原因是你当前本地分支版本低于远程分支,这个有好几种解决方法,我这里使用 git pull。

图片关键词


② 在 master 分支执行 git pull:

图片关键词


③ 存在冲突的情况下:

1) 修改前:

图片关键词


2) 在 master 分支执行 git rebase fox:这个由于产生了冲突,所以 HEAD 指向和 master 指向就不一样了,而且本地产生冲突。

图片关键词


3) 解决冲突、并 git add . 然后执行 git rebase --continue:

图片关键词


4. merge:

(1) 说明:将指定提交合并到当前分支


(2) 作用:

① 用于git-pull中,来整合另一代码仓库中的变化(即:git pull = git fetch + git merge)。

② 用于从一个分支到另一个分支的合并。


(3) 命令:

① git merge-m:

1) 合并分支的时候可能存在冲突,也可能不存在冲突。如果不存在冲突则它会自动提交,其提交消息为 msg;如果存在冲突则需要本地解决后手动 commit。

(4) 会不会产生新的提交的两种情况:

① 不会产生新的提交:

1) 说明:

a. 这种实际上不会产生冲突,因为提交就一条线。

2) 流程:

合并前:

图片关键词


b.在 fox 分支执行 git merge matser,即在 fox 分支合并 master 分支:

a)说明:因为 fox 分支比master 更新,所以这时候 git b)会提示你已经是最新版本了。

c)图:

图片关键词

c. 在 master 分支执行 git merge fox,即在 master 分支合并 fox 分支:

a) 说明:由于提交是一条线,所以这时只需要 master 移动指向即可,不需要产生新的提交。

b) 图:

图片关键词


② 会产生新的提交:

1) 流程:

a. 合并前:

图片关键词


b. 在 fox 分支执行 git merge matser,即在 fox 分支合并 master 分支:

图片关键词


5. merge 和 rebase的区别:

(1) 流程:

图片关键词


(2) 修改前:

① 在 master 使用 rebase 合并 fox:

图片关键词


② 在 master 使用 merge 合并 fox:

图片关键词



05

用于操作远程仓库的命令:


1. 关联远程仓库:

(1) 添加远程仓库地址:

① git remote add origin https://gitee.com/XXXX/git.git:

1) 如果该文件夹是没有管理远程仓库的,则可以使用这个来添加远程仓库。


(2) 更换远程仓库地址:

① git remote set-url origin https://gitee.com/XXXX/netty.git:

1) 这个是更换,区别于添加。


2. 在本地创建一个远程仓库:

(1) 方案一:

① git clone https://gitee.com/XXXX/git.git

(2) 方案二:

① git init

② git remote add origin https://gitee.com/XXXX/git.git:至此,本地并没有对应的远程分支,所以需要检出远程分支。

③ git checkout master


3. 从远程资源库拉取数据到本地资源库:

(1) git clone:

① git clone  https://gitee.com/XXXX/git.git:

1) 从远程仓库拉取一个完整备份。

(2) git pull:

① git pull <远程主机名> <远程分支名>:<本地分支名>:

1) 从远程分支拉取代码,其本质相当于是

2) :git pull = git fetch + git merge。

② git pull --rebase:

1) git pull --rebase = git fetch + git rebase


4. 从本地资源库推送数据到远程资源库:

(1) git push:

① git push <远程主机名> <本地分支名>:<远程分支名>

② git push <远程主机名> <本地分支名>:

1) 如果本地分支名与远程分支名相同,则可以省略<远程分支名>。

③ git push --force origin master:

1) 强制推送,会导致远程资源库被覆盖,这个尽量避免使用。


06

用于操作本地仓库分支的命令:


1. 创建本地新分支:

(1) git branch fox

① 创建分支。


2. 创建远程分支:

(1) git push origin::

① git push origin fox:fox-t:将本地的 fox 分支推送到远程资源库,其名为 fox-t。


3. 切换本地分支:

(1) git checkout fox:

① 切换分支。

(2) git checkout -b fox:

① 创建并切换分支,相当于是 git branch 和 git checkout 和合集。


4. 切换远程分支:

(1) git checkout -b 本地分支名 origin/远程分支名


5. 删除本地资源库的分支:

(1) git branch -D:

① git branch -D fox:删除本地资源库名为 fox 的分支。


6. 删除远程资源库的分支:

(1) git push origin --delete:

① git push origin --delete fox:删除远程资源库上名为 fox 的分支。


7. 查看分支:

(1) git branch:

(2) 说明:查看本地分支。

(3) 图:

(4) git branch -r:查看远程分支。

(5) git branch -a:查看所有分支。


8. git stash:

(1) 说明:

① stash 本质上是将暂存区和本地资源库的内容进行提交(这个是提交是在本分支开辟了另外一个分支,当然这个分支是临时的,之后是要被抛弃的)。


(2) 流程图:

① 修改前:

图片关键词


② git stash save 's-1’:其提交消息即 s-1

图片关键词


③ 再次执行 git stash save ’s-2’:此时相当于是重新提交了一次,且会覆盖上次 stash ,其提交消息为 s-2。


图片关键词


④执行 git stash pop stash@{0} :恢复最近一次存储, stash 存储是一个栈,即后进先出。


图片关键词


⑤ 修改代码后提交到本地资源库:

图片关键词


⑥ 提交到远程分支:

图片关键词


(3) 命令:

① git stash save 's-1':存储暂存区的内容。

② git stash list:查看存储列表。

③ git stash clear:清空存储内容。

④ git stash drop stash@{num}:删除某一个,stash@{num} 是 save 时自动产生的编号。

⑤ git stash pop stash@{num}:恢复,num是可选项,通过git stash list可查看具体值。只能恢复一次。

⑥ git stash apply stash@{num}:恢复,num是可选项,通过git stash list可查看具体值。可回复多次。


(4) 注意:多次执行 git stash save ‘XXX’ 的时候,是按栈存储的(后进先出),即执行 git stash save ’s-1’ && git stash save ’s-2’。则  stash@{0} 对应 s-2;stash@{1} 对应 s-1。


(5) 用途:

① git stash 本质上是在本地分支中建立了一个临时的、会被抛弃的分支,所以有些我们并不想把代码提交上去的时候就可以使用这个。

② pull 的时候保护本地修改的代码。



07

其他的工具类的命令


1. 初始化本地仓库:

(1) git init:

① 初始化本地仓库,会产生一个 .git 文件,所有 git 的数据都会放在这里。


2. 查看日志:

(1) git log:

① 说明:

1) git log 显示的是提交记录(提交到本地仓库的)。

2) 默认情况下是按提交时间顺序从最近的开始。

3) 只要提交到本地仓库上的就会显示,不需要提交到远程仓库。但他们是有区别的,origin/master 的位置不一样。


(2) 图:

① 最后一次只提交到本地仓库,没有提交到远程仓库:

图片关键词


② 全部提交到远程仓库:

图片关键词


(3) git log -1:

① 说明:

1) 只显示最近的一条提交记录。

② 图:

图片关键词


(4) git log -S book:

① 说明:

1) 搜索提交历史,查询出第一次提交 book 这个内容(不是文件,是内容)是哪一次。

② 图:

图片关键词


(5) git log --pretty=oneline:

① 说明:

1) 简化输出

② 图:

图片关键词


(6) git log --all:

① 说明:

1) 默认情况下 git log 只能查询 HEAD 指向之前的,但如果我们用 git reset … 命令使得我们当前 HEAD指向发生了改变,那就无法查询全部了(当前分支),此时我们就可以加上 --all。

② 图:

图片关键词


3. 查看状态:

(1) git status:

① 说明:

1) 会显示当前所在本地分支。

2) 该命令显示的是暂存区的文件,其他的不会被显示;而这一个区的文件一共有 新增、修改、删除三种状态。

② 图:

图片关键词


(2) git status -s:

① 说明:

1) 是 git status 的简写。

② 图:

图片关键词


08

使用二分法调试


1. 说明:

(1) 假设我们一共提交了10次,但发现有问题,可是我们不知道是哪一次提交引起的,这时候我们就可以使用 git rebase 来进行调试。

(2) git rebase 是一种很有用的命令,用来查找哪一次代码提交引入了错误。

(3) 它使用的是二分法,既[1, 10],它会先定位到5,然后你可以使用 git  bisect good 定位到7(既[5,10]),用 git bisect bad定位到3(既[1,5])。使用 git bisect reset 恢复到最近一次提交。

图片关键词


2. 流程:

(1) git log --pretty=oneline:我们查询出相应指针编号。

图片关键词

(2)git bisect start HEAD 16ae850e14f9e15d5a71bf2df581be4edcd6cda3:它会让你本地仓库的 HEAD 指针指向 HEAD 和 16ae850e14f9e15d5a71bf2df581be4edcd6cda3 的中间。

图片关键词


(3) git bisect good:向前再次二分

图片关键词

(4) git bisect bad:向后再次二分。

(5) git bisect reset:退出 bisect 模式,恢复到最近一次提交。

图片关键词



标签: git
首页
产品
新闻
联系