Git相关原理

一 Git 是什么?
Git 是一种分布式开源 版本管理工具(VCS),你可以用它存储代码、跟踪修订历史记录、合并代码更改,并在需要时恢复为较早的代码版本。

二 Git 分区

  1. 工作区 working directory 是「工作目录」,也就是我们肉眼能够看到的文件
  2. 暂存区 (Index)
  3. 本地仓库区(Repository)
  4. 远程仓库区 (Remote)

    三 git 常用命令行

文件夹中查看隐藏文件
mac中快捷键: cmd+shift+.
windows中

HEAD 代表什么?
HEAD 是引用中最特殊的一个:HEAD 是指向当前 commit 的引用,它具有唯一性,每个仓库中只有一个 HEAD。它是指向当前 commit 的引用。所谓当前 commit这个概念很简单,它指的就是当前工作目录所对应的 commit。
每次当有新的 commit 的时候,工作目录自动与最新的 commit 对应;而与此同时,HEAD 也会转而指向最新的 commit。事实上,当使用 checkout、reset 等指令手动指定改变当前 commit 的时候,HEAD 也会一起跟过去。
总之,当前 commit 在哪里,HEAD 就在哪里,这是一个永远自动指向当前 commit 的引用,所以你永远可以用 HEAD 来操作当前 commit。
HEAD 是 Git 中一个独特的引用,它是唯一的。而除了 HEAD 之外,Git 还有一种引用,叫做 branch(分支)。HEAD 除了可以指向 commit,还可以指向一个 branch,当它指向某个 branch 的时候,会通过这个 branch 来间接地指向某个 commit;另外,当 HEAD 在提交时自动向前移动的时候,它会像一个拖钩一样带着它所指向的 branch 一起移动。
尽管在 Git 中,branch 只是一个指向 commit 的引用,但它有一个更通俗的理解:你还可以把一个 branch 理解为从初始 commit 到 branch 所指向的 commit 之间的所有 commits 的一个「串」。 git rebase 变基的本质就是,通过改变 branch 初始commit 的位置。
如何创建分支
// 在dev上 新建分支
git branch feature-line
// 但HEAD 依旧是指向的 dev分支最新的commit。需要执行下面操作来将HEAD指向新分支
git checkout feture-line

//或者一步到位,创建并将HEAD执向新分支
git checkout -b feature-line
Git 中的 HEAD 和每一个 branch 以及其他的引用,都是以文本文件的形式存储在本地仓库 .git 目录中,而 Git 在工作的时候,就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。

push的本质
push 是把当前的分支上传到远程仓库,并把这个 branch 的路径上的所有 commits 也一并上传
push 的时候,如果当前分支是一个本地创建的分支,需要指定远程仓库名和分支名,用 git push origin branch_name 的格式,而不能只用 git push;或者可以通过 git config 修改 push.default 来改变 push 时的行为逻辑
push 的时候之后上传当前分支,并不会上传 HEAD;远程仓库的 HEAD 是永远指向默认分支(即 master)的
push -f 的本质:
Merge本质 合并commits
Pull 操作在做什么: fetch 拉取远程最新的代码,然后将新的commit merge 到本地分支的过程。
Merge 在做什么,合并,指定一个 commit,把它合并到当前的 commit 来;
从目标 commit 和当前 commit (即 HEAD 所指向的 commit)分叉的位置起,把目标 commit 的路径上的所有 commit 的内容一并应用到当前 commit,然后自动生成一个新的 commit。
适用场景

  1. 合并分支 - 当一个 branch 的开发已经完成,需要把内容合并回去时,用 merge 来进行合并。
  2. 特殊情况:冲突。
    merge 在做合并的时候,是有一定的自动合并能力的:如果一个分支改了 A 文件,另一个分支改了 B 文件,那么合并后就是既改 A 也改 B,这个动作会自动完成;如果两个分支都改了同一个文件,但一个改的是第 1 行,另一个改的是第 2 行,那么合并后就是第 1 行和第 2 行都改,也是自动完成。
    但,如果两个分支修改了同一部分内容,merge 的自动算法就搞不定了。这种情况 Git 称之为:冲突(Conflict)。直白点说就是,你的两个分支改了相同的内容,Git 不知道应该以哪个为准。如果在 merge 的时候发生了这种情况,Git 就会把问题交给你来决定。具体地,它会告诉你 merge 失败,以及失败的原因:
  3. 特殊情况 2:HEAD 领先于目标 commit
    如果 merge 时的目标 commit 和 HEAD 处的 commit 并不存在分叉,而是 HEAD 领先于目标 commit,那么 merge 就没必要再创建一个新的 commit 来进行合并操作,因为并没有什么需要合并的。在这种情况下, Git 什么也不会做,merge 是一个空操作。
  4. 特殊情况 3:HEAD 落后于 目标 commit——fast-forward (快速前移)

git add 的本质 ?
将文件的修改的内容添加到暂存区! (注意,不是整个文件) ,当我们git add 一个文件后,如果对文件又做了修改,那么还需要继续进行一次 git add
git commit --amend 的本质, 会把当前 commit 里的内容和暂存区(stageing area)里的内容合并起来后创建一个新的 commit,用这个新的 commit 把当前 commit 替换掉。所以 commit --amend 做的事就是它的字面意思:对最新一条 commit 进行修正。Git 会把你带到提交信息编辑界面。可以看到,提交信息默认是当前提交的提交信息。你可以修改或者保留它,然后保存退出。然后,你的最新 commit 就被更新了。

git checout 的本质?
checkout 的本质是签出指定的 commit,所以你不止可以切换 branch,也可以直接指定 commit 作为参数,来把 HEAD 移动到指定的 commit。
git checkout branch名 的本质,其实是把 HEAD 指向指定的 branch,然后签出这个 branch 所对应的 commit 的工作目录。所以同样的,checkout 的目标也可以不是 branch,而直接指定某个 commit。
checkout 和 reset 的不同
checkout 和 reset 都可以切换 HEAD 的位置,它们除了有许多细节的差异外,最大的区别在于:reset 在移动 HEAD 时会带着它所指向的 branch 一起移动,而 checkout 不会。当你用 checkout 指向其他地方的时候,HEAD 和 它所指向的 branch 就自动脱离了。

事实上,checkout 有一个专门用来只让 HEAD 和 branch 脱离而不移动 HEAD 的用法:
git checkout --detach
执行这行代码,Git 就会把 HEAD 和 branch 脱离,直接指向当前 commit:

git reset 的本质
reset 的本质:移动 HEAD 以及它所指向的 branch。
--soft 软回退 : HEAD指针向前移动,将对应commit修改 回退到暂存区
--hard 强回退:HEAD指针向前移动,对应的修改的内容不保存。
--mixed 默认回退: HEAD指针向前移动,将对应commit修改 回退到工作区

利用原理解决的几个问题

  1. 没有推到远程的分支 被意外删除了,怎么找回对应的修改代码?
    方法一:
    git checkout -b recover-branch 2d3ade878(通过git reflog 找到被删除分支的最后一次commit提交)
    方法二:
    // 先签出,看效果。再通过签出的当前commit 进行新建分支。
    git checkout c08de9a
    git checkout -b branch1
  2. 刚提交的合并申请的代码有误,被打回重新修改,应该如何操作?commit 的 message 有问题如何重新修改提交?
    先修改代码,然后git commit --amend
    然后如果要改message ,就 i 进入修改模式,改后,esc退出修改模式,:wq 保存并推出vim
  3. 本地分支如何进行代码回退操作?
    git reset 操作 (--hard, 或者 --soft ,或者默认)
  4. 线上dev 开发分支或者 master分支 如何进行代码回退操作?
    git revert 操作
    git revert HEAD 撤销当前的commit
    git revert HEAD^ 撤销前一次commit
    git revert commitID 撤销指定的某次commit
    reverse 如何回退连续的多个commit,并且合并成一次回退commit记录?
  5. 已经提交了好几个commit了,才发现原来提交的某个commit 的message(或者提交的代码有问题),如何进行正确的补救?
    rebase -i 是 rebase --interactive 的缩写形式,意为「交互式 rebase」
    所谓「交互式 rebase」,就是在 rebase 的操作执行之前,你可以指定要 rebase 的 commit 链中的每一个 commit 是否需要进一步修改。
    Pick 应用当前commit
    S 合并
    删除某一行pick 就相当于把对应的commit删除掉了
    6.已经提交了好几个commit了,才发现原来提交的某个或者某两个commit 不应该被提交,如何进行正确操作将这两个commit记录进行删除?
    方法一:
    git rebase -i 将对应的pick 行删除即可
    方法二:
    git rebase --onto

参考文档 :Git原理详情及实用指南

posted on 2023-10-17 08:53  长安城下翩翩少年  阅读(55)  评论(0编辑  收藏  举报