关于 git 常用知识,看这一篇就够了 !

478 阅读27分钟

git 基本介绍 blog.csdn.net/u011535541/…

概念

一:Git是什么?
Git是目前世界上最先进的分布式版本控制系统。
工作原理 / 流程:

image.png Workspace:工作区
Index / Stage:暂存区
Repository:仓库区(或本地仓库)
Remote:远程仓库

** SVN与Git的最主要的区别?**

SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。

Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

git的工作流

工作区:即自己当前分支所修改的代码,git add xx 之前的!不包括 git add xx 和 git commit xxx 之后的。

暂存区:已经 git add xxx 进去,且未 git commit xxx 的。

版本库(本地仓库):已经git commit -m xxx 提交到本地版本库(本地仓库)的对应分支。

工作区

就是你在电脑上看到的目录,比如目录下testgit里的文件(.git隐藏目录版本库除外)。或者以后需要再新建的目录文件等等都属于工作区范畴。

暂存区

英文名stage/index,工作区有一个隐藏目录.git,这个不属于工作区,这是版本库。其中版本库里面存了很多东西,其中最重要的就是stage(暂存区),工作区的内容经过 git add . 提交到暂存区,再经过 git commit 提交到版本库,多次 git add. 可以通过一次 git commit 提交到版本库的当前分支上。

版本库(本地仓库)

什么是版本库?你使用git init 后会在文件夹中产生一个.git的文件夹,这个就是版本库,版本库又名仓库,英文名repository,你可以简单的理解一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改,删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻还可以将文件”还原”,git创建版本库后,会自动创建master分支,以及指向master的指针HEAD。

所以创建一个版本库也非常简单,如下我是D盘 –> www下 目录下新建一个testgit版本库。

  1. 创建版本库:通过命令 git init 把这个目录变成git可以管理的仓库

这时候你当前testgit目录下会多了一个.git的目录,这个目录是Git来跟踪管理版本的,没事千万不要手动乱改这个目录里面的文件,否则,会把git仓库给破坏了。

image.png 2. 把文件添加到版本库中。

首先要明确下,所有的版本控制系统,只能跟踪文本文件的改动,比如txt文件,网页,所有程序的代码等,Git也不列外,版本控制系统可以告诉你每次的改动,但是图片,视频这些二进制文件,虽能也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是知道图片从1kb变成2kb,但是到底改了啥,版本控制也不知道。

image.png

image.png

image.png

** 理解工作区与暂存区的区别?**

工作区:就是你在电脑上看到的目录,比如目录下testgit里的文件(.git隐藏目录版本库除外)。或者以后需要再新建的目录文件等等都属于工作区范畴。

版本库(Repository):工作区有一个隐藏目录.git,这个不属于工作区,这是版本库。其中版本库里面存了很多东西,其中最重要的就是stage(暂存区),还有Git为我们自动创建了第一个分支master,以及指向master的一个指针HEAD。`

我们前面说过使用Git提交文件到版本库有两步:

第一步:是使用 git add 把文件添加进去,实际上就是把文件添加到暂存区。

第二步:使用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支上。

我们继续使用demo来演示下:

我们在readme.txt再添加一行内容为4444444,接着在目录下新建一个文件为test.txt 内容为test,我们先用命令 git status来查看下状态,如下:

image.png

远程仓库

在了解之前,先注册github账号,由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的,所以需要一点设置:
第一步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果有的话,直接跳过此如下命令,如果没有的话,打开命令行,输入如下命令:

ssh-keygen -t rsa –C “youremail@example.com”, 由于我本地此前运行过一次,所以本地有,如下所示:

image.png id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

第二步:登录github,打开” settings”中的SSH Keys页面,然后点击“Add SSH Key”,填上任意title,在Key文本框里黏贴id_rsa.pub文件的内容。

image.png 点击 Add Key,你就应该可以看到已经添加的key。

image.png 如何添加远程库?
现在的情景是:我们已经在本地创建了一个Git仓库后,又想在github创建一个Git仓库,并且希望这两个仓库进行远程同步,这样github的仓库可以作为备份,又可以其他人通过该仓库来协作。

首先,登录github上,然后在右上角找到“create a new repo”创建一个新的仓库。如下:

image.png 在Repository name填入testgit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库:

image.png 目前,在GitHub上的这个testgit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。 现在,我们根据GitHub的提示,在本地的testgit仓库下运行命令:

git remote add origin github.com/tugenhua070…

所有的如下:

image.png 把本地库的内容推送到远程,使用 git push命令,实际上是把当前分支master推送到远程。

由于远程库是空的,我们第一次推送master分支时,加上了 –u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以立刻在github页面中看到远程库的内容已经和本地一模一样了

从现在起,只要本地作了提交,就可以通过如下命令:

git push origin master

把本地master分支的最新修改推送到github上了,现在你就拥有了真正的分布式版本库了。

  1. 如何从远程库克隆?

    上面我们了解了先有本地库,后有远程库时候,如何关联远程库。

    现在我们想,假如远程库有新的内容了,我想克隆到本地来 如何克隆呢?

    首先,登录github,创建一个新的仓库,名字叫testgit2.如下:

image.png 现在,远程库已经准备好了,下一步是使用命令git clone克隆一个本地库了。如下所示:

image.png

总结:

1.先有本地仓库,再创建远程仓库

git remote add origin git@*******/**.git

这时候相当于连接上了远程仓库:这时候你的远程仓库的名字就是origin,这是git默认对于远程版本库的叫法

下一步就是将你的本地库推送到远程库上: git push -u origin master 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

2.先有远程仓库,再创建本地仓库

使用git clone git@*******/**.git 可以直接从远程仓库克隆一个本地库

如果有多个人协作开发,那么每个人各自从远程克隆一份就可以了。 你也许还注意到,GitHub给出的地址不止一个,还可以用github.com/michaelliao… 使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。

分支管理(创建与合并分支)

先解释一下分支的概念:
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向当前分支,分支指向当前最新的提交。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

image.png 每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。 当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

image.png 从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

image.png 假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

image.png 合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支

image.png note: 对于所有分支而言, 工作区和暂存区是公共的。 分支修改后没有提交是无法切换到另一分支的 $ git checkout master error: Your local changes to the following files would be overwritten by checkout: README.md Please commit your changes or stash them before you switch branches. 但是我看到有些人是可以违规切换到其他分支的,不太清楚这是怎么操作的(应该是没有冲突的时候就可以切换)

例子:
首先,我们来创建dev分支,然后切换到dev分支上。如下操作:

image.png git checkout 命令加上 –b参数表示创建并切换,相当于如下2条命令

git branch dev

git checkout dev

git branch查看分支,会列出所有的分支,当前分支前面会添加一个星号。然后我们在dev分支上继续做demo,比如我们现在在readme.txt再增加一行 7777777777777

首先我们先来查看下readme.txt内容 如下:

image.png

现在dev分支工作已完成,现在我们切换到主分支master上,继续查看readme.txt内容如下: image.png 现在我们可以把dev分支上的内容合并到分支master上了,可以在master分支上,使用如下命令 git merge dev 如下所示:\

image.png git merge命令用于合并指定分支到当前分支上,合并后,再查看readme.txt内容,可以看到,和dev分支最新提交的是完全一样的。

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

合并完成后,我们可以接着删除dev分支了,操作如下: image.png 总结创建与合并分支命令如下:

查看分支:git branch

创建分支:git branch name

切换分支:git checkout name

创建+切换分支:git checkout –b name

合并某分支到当前分支:git merge name

删除分支:git branch –d name

解决冲突

image.png 如上图,你解决后的文件被提交到下一个commit节点上去了

分支管理策略

  1. 通常合并分支时,git一般使用”Fast forward”模式,在这种模式下,删除分支后,会丢掉分支信息,现在我们来使用带参数 –no-ff来禁用”Fast forward”模式。首先我们来做demo演示下: 创建一个dev分支。
    修改readme.txt内容。
    添加到仓库。
    切换回主分支(master)。
    合并dev分支,使用命令 git merge –no-ff -m “注释” dev
    查看历史记录
    截图如下:

image.png

分支管理策略

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; 那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本; 你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。 所以,团队合作的分支看起来就像这样:

image.png

Bug分支:

这一节点主要讲述的内容是,当你正在开发dev分支,但是突然需要你修改一个bug,但是你目前的改动还不能提交(commit),怎么办? 可以使用git stash将现在工作区的操作全部保存下来 这时候你修改完成bug后:回到dev分支,可以使用git stash list查看你的保存的状态 工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;dorp是一条一条的删除,(从最新的保存的条目往前删,保存的条目是从上往下由旧到新)可以指定版本git stash drop {{ stash id }} eg:git stash drop 1 另一种方式是用git stash pop,恢复的同时把stash内容也删了:

当你多次使用git stash想要恢复到指定的状态时
可以使用git stash apply {{stash id}}  eg:git stash drop 1
也可以回到你开发时的状态,恢复工作区的操作是一个merge操作,如果当前工作区有改动,要先放到暂存区,才能恢复,
恢复的过程是一个merge过程也会出现冲突。

注意:当你在其他分支进行提交,但你又不想将整个分支都合并到你现在发分支:可以使用git cherry-pick 命令
真实场景:在主分支上修改bug,提交后,你的dev上分支肯定没有修改好这个bug,但你又不想将主分支上的代码全部都移交过来,
这时候你就可以使用 `git cherry-pick <commitHash>` 只将主分支的这次提交合并过来;
注意,这里的commitHash指的是你想要合并过来的操作的commitHash

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令
git branch --set-upstream-to origin/

多人协作

当你从远程库克隆时候,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程库的默认名称是origin。

要查看远程库的信息 使用 git remote
要查看远程库的详细信息 使用 git remote –v
如下演示:

image.png 一:推送分支:
1. 推送分支就是把该分支上所有本地提交到远程库中,推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上: 使用命令 git push origin master

那么一般情况下,那些分支要推送呢?
master分支是主分支,因此要时刻与远程同步。
一些修复bug分支不需要推送到远程去,可以先合并到主分支上,然后把主分支master推送到远程去。

二:抓取分支: 现在我们的小伙伴要在dev分支上做开发,就必须把远程的origin的dev分支到本地来,于是有两种方式:

  1. 远端有dev分支,本地也有远端的分支 origin/dev,用checkout切换到dev分支进行开发,git pull 后在最新的dev分支上开发。
  2. 远端有dev分支,本地没有,用git fetch获取远端的dev分支,用checkout切换到dev分支进行开发。
  3. 远端没有dev分支,本地git branch -b dev,创建本地分支,在dev上进行开发,开发完成后把dev分支推送到远程库时,推送失败了,如图: image.png 原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:如下: image.png 这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的 解决冲突完全一样。解决后,提交,再push

因此:多人协作工作模式一般是这样的:\

  1. 没有分支在远端创建分支,本地git checkout,可以直接切换到远端分支,或者创建本地分支再于远端分支建立连接.
  2. 开发前如果是多人开发的分支,先git pull 最新的代码再进行开发。
  3. 开发完 放到暂存区,提交到本地版本库对应的分支,再 git push 推送到远程版本库的对应的分支。
  4. 如果合并有冲突,则需要解决冲突,并在本地提交。再用git push origin branch-name推送。

命令操作

日志

git log (顺序:最新的提交在最上面)

  • --oneline: 把每一个提交压缩到了一行中
  • --decorate: 让 git log 显示指向这个提交的所有引用(比如说分支、标签等)
  • --color: 彩色输出信息
  • --graph: 绘制一个 ASCII 图像来展示提交历史的分支结构
  • --all:查看所有分支的提交历史

删除

一般情况下,可以直接在文件目录中把文件删了,或者使用如上rm命令,如果我想彻底从版本库中删掉了此文件的话,可以git add 后使用git commit删除版本库,删除后提交才能保持对文件的追踪
只要没有commit之前,如果我想在版本库中恢复此文件如何操作呢?\

请使用git checkout – test.txt将文件夹恢复到与版本库一致

合并分支

git merge: 默认 fast forward
跟踪上游存储库,您没有提交任何本地更改,现在您想要更新到更新的上游版本。 在这种情况下,一个新的 不需要提交来存储合并的历史记录; 相反,HEAD(连同索引)被更新为指向命名的提交,没有 创建额外的合并提交。此操作会在删除分支后,丢失被删除分支的信息,可以使用 --no-ff 选项抑制此行为。

image.png image.png options:
--abort:中止当前的冲突解决过程,并尝试重建合并前的状态。

note:
js 1. 如果在合并开始时存在未提交的工作树更改,则 git merge --abort 在某些情况下将无法重建这些变化。 因此,建议在运行 git merge 之前始终提交或隐藏您的更改。
2. git merge --abort 等效于 git reset --merge 当 MERGE_HEAD 存在时,除非 MERGE_AUTOSTASH 也存在,在这种情况下 git merge --abort 将 stash 条目应用于工作树,而 git reset --merge 将在 stash 列表中保存隐藏的更改。

--quit: 忘记当前正在进行的合并。 保持索引和工作树原样。 如果存在 MERGE_AUTOSTASH,则存储条目将是保存到存储列表。
--continue:在 git merge 由于冲突而停止后,您可以通过运行 git merge --continue 来结束合并。 --squash, --no-squash:使下一个 git commit 命令创建合并提交。
--commit, --no-commit:请注意,快进更新不会创建合并提交,因此无法使用 --no-commit 停止这些合并。 因此,如果你想要确保您的分支不会被合并命令更改或更新,请使用 --no-ff 和 --no-commit。

拉取分支

git pull: 将远程存储库中的更改合并到当前分支中。 在默认模式下, git pull 是 git fetch 后跟 git merge 的简写。FETCH_HEAD。 更准确地说, git pull 使用给定的参数运行 git fetch 并调用 git merge 将检索到的分支头合并到当前分支中。

note: 
如果任何远程更改与本地未提交的更改重叠,合并将自动取消并且工作树不受影响。
不会影响stash 中隐藏的工作区(自己理解)

options:
-q, --quiet:
--cleanup:此选项确定在提交之前如何清理合并消息
--set-upstream:如果远程成功获取,则拉取并添加上游(跟踪)引用\

git fetch: 拉取远程分支。

聊下git merge --squash

你经常会面临着将dev分支或者很多零散的分支merge到一个公共release分支里。

但是有一种情况是需要你处理的,就是在你的dev的分支里有很多commit记录。而这些commit是无需在release里体现的。

--squash 用于把多个提交合并成一次提交,并且merge --squash 时会暂停commit提交,可输入本次合并提交的记录。要不然merge会自动提交commit。

Git撤销&回滚操作

我们暂且将“本地仓库”的代码还原操作叫做“撤销”!我们将已被提交到“远程仓库”的代码还原操作叫做“回滚”!注意:对远程仓库做回滚操作是有风险的,需提前做好备份和通知其他团队成员!

1.当你写错了东西,但是你没有git add也没有git commit 的情况下:

使用git checkout – 文件名 (git checkout –- .) 工作区做的修改全部撤销,就可以回到和版本库中一样的文件了

2.当你写错了东西,但是你使用git add已经提交到暂存区了,但是没有使用git commit提交到版本库中

git reset HEAD 以把暂存区的修改撤销掉(unstage),重新放回工作区,然后 git checkout – 文件名(git checkout –- .),就可以回到和版本库中一样的文件了

3.当你写错了东西,但是你使用git add已经提交到暂存区了,也使用git commit提交到版本库中了

那么直接使用 git reset --hard HEAD^撤回到上一个commit就行了

note: git checkout – file命令中的–很重要,没有–,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

4.当你提交到远程了(回滚)

1)通过git reset是直接删除指定的commit
    git log # 得到你需要回退一次提交的commit id
    git reset --hard commit id
    git push origin HEAD --force # 强制提交一次,之前错误的提交就从远程仓库删除
2)通过git revert是用一次新的commit来回滚之前的commit
    git log # 得到你需要回退一次提交的commit id
    git revert   # 撤销指定的版本,撤销也会作为一次提交进行保存
    
    `git reset 和 get revert 的区别:`
   - git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留;
   - git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除

5.修改的文件已被git commit,但想再次修改不再产生新的Commit

`# 修改最后一次提交 #`
`git add sample.txt`
`git commit --amend -m "说明"`

6.刚才我发现之前的某次提交太愚蠢了,现在想要干掉它(对历史多个commit进行处理或者合并多个commit)

其他:git常用命令

难点:

1.git reset [--hard|soft|mixed|merge|keep] [commit|HEAD]:是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除。

  • git reset --hard HEAD^ (使用HEAD来表示当前分支,分支再指向最新的提交,那么上一个版本就是HEAD^ ,上上个版本是HEAD^ ^ ,那么一百个版本以前是什么 ,肯定不 是HEAD ^ 后面跟100^,而是使用HEAD~100的方式退回到100个版本以前)
  • git reset --hard commitId (可以不用写全,git会自己查找) note: reset 后你已经找不到前面的commit id了你该怎么办:可以使用git reflog命令 (顺序:最新的提交在最上面,reset操作也会生成一条记录在最上面),这个命令记录了你所有的提交,这样你就可以找到对应的commit id了。 2.git revert:用一次新的commit来回滚之前的commit,之前的commit记录不会丢失。

3.git rebase:如果你想对历史多个commit进行处理,可以选择git rebase -i,只需删除对应的记录就好。rebase还可对 commit 消息进行编辑,以及合并多个commit。

git merge 和 git rebase 的区别

前段时间由于某种原因,开始接手开发公司前端Vue搭建的项目

该前端项目采用的是基于git rebase的形式去合并代码,而我之前使用git一直都是采用merge的形式合并分支代码,对于rebase一概不知

故此利用碎片时间学习整理一下关于git rebase的原理以及其和git merge的区别是什么,我会采用实际的案例描述二者的区别

准备工作

  • git 客户端安装(只要git bash即可)
  • github上新建一个项目

1.create project
2.项目clone到本地
3.clone完成以后进入该项目文件夹下,准备工作完毕

模拟日常开发

同学A:

  • 执行git log

此时可以看出此时该项目仅有一次提交记录

  • 执行新增文件a.txt,并本地提交一次后再次执行git log

这个时候打开github,刷新该项目的commit记录 发现远程仓库还是只有一次提交记录的,说明A同学还没有将自己最新的修改push到远程仓库,其他同学这个时候是看不到A的最新提交的

  • A同学将自己的最新提交Push到远程仓库
  • 再次刷新github 提交记录,发现已经多了一个A同学提交的最新记录了

切分支开发

  • 基于已有两次提交记录的本地master分支检出一个新分支dev,并将该分支推到远程仓库

  • 查看远程仓库,多了一个dev分支

  • 此时本地的git分支图类似如下

A同学开发功能

假设A同学基于dev分支开发功能,在本地新做了三次代码提交,git log 如下

那么此时的git分支图如下

  • 重点

如果此时在A同学准备进行第四次本地提交之前,另一个同学B向远程仓库推送了一个master分支的提交,即此时master实际的提交已经向前走了

我们这个时候在github上操作一次commit,模拟另一个同学此时push了master分支

  • A同学本地更新一下master分支

发现master分支已经向前走了一次提交,此时的分支图如下

此时我们知道A同学开发的dev分支是基于C2提交点切出来的,而这个时候master分支已经被更新了

如果A同学开发完毕,需要将其所作的功能合并到master分支 ,他可以有两种选择

直接git merge

如果A同学选择用git merge的方式进行合并dev到master分支,那么git会这么做

  1. 找出dev分支和master分支的最近共同祖先commit点,即C2
  2. 将dev最新一次commit(C5)和master最新一次commit(C6)合并后生成一个新的commit(C7),有冲突的话需要解决冲突
  3. 将以上两个分支dev和master上的所有提交点(从C2以后的)按照提交时间的先后顺序进行依次放到master分支上

git rebase 后再git merge

  1. rebase之前需要经master分支拉到最新
  2. 切换分支到需要rebase的分支,这里是dev分支
  3. 执行git rebase master,有冲突就解决冲突,解决后直接git add . 再git rebase --continue即可

此时的git log如下

可以发现其一并没有多出一次commit,其二dev后面几次提交的commit hash值已经变了,包括C3,C4,C5

  1. 切换到master分支,执行git merge dev

发现采用rebase的方式进行分支合并,整个master分支并没有多出一个新的commit,原来dev分支上的那几次(C3,C4,C5)commit在rebase之后其hash值发生了变化,不在是当初在dev分支上提交的时候的hash值了,但是提交的内容被全部复制保留了,并且整个master分支的commit记录呈线性记录

其分支图最终如下

总结

  • git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式
  • git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的patch,并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit点,可以保持整个分支树的完美线性

另外值得一提的是,当我们开发一个功能时,可能会在本地有无数次commit,而你实际上在你的master分支上只想显示每一个功能测试完成后的一次完整提交记录就好了,其他的提交记录并不想将来全部保留在你的master分支上,那么rebase将会是一个好的选择,他可以在rebase时将本地多次的commit合并成一个commit,还可以修改commit的描述等

疑难问题: git 存储凭证

image.png