人生难得是欢聚,惟有别离多 - 《城南旧事》

0.整体认识

图片摘自:程序员三毛

image-20241004165832258

Git 的四个主要区域:

  1. 工作区(Working Directory)
    • 即你在本地文件系统中看到的文件。开发者通常在工作区修改代码。
  2. 暂存区(Staging Area/Index)
    • 暂存区是一个临时区域,保存你标记为准备提交的更改。可以将其看作是一个缓存区,记录哪些文件的更改将进入下一次提交。
  3. 本地仓库(Local Repository)
    • 本地仓库存储了你所有的提交历史记录。每次提交(git commit)都会将暂存区的变化保存到本地仓库。
  4. 远程仓库(Remote Repository)
    • 远程仓库是存放在服务器上的 Git 仓库,多个开发者可以共享该仓库。通常使用 git push 将本地仓库的变更推送到远程仓库,或使用 git pull 从远程仓库中拉取最新的代码。

Git 工作流程详细说明:

1. 在工作区修改文件

  • 开发者通常在工作区中编辑文件。
  • 文件的状态可以是未跟踪的(untracked),已跟踪但未修改的,已修改但未暂存的。

2. 将修改添加到暂存区:git add

  • 当你修改了文件后,使用 git add 将更改从工作区添加到暂存区。
  • 可以通过 git add <file> 将特定文件添加到暂存区,或者使用 git add . 将工作区中的所有更改都添加到暂存区。

3. 提交更改到本地仓库:git commit

  • 使用 git commit 命令将暂存区的内容提交到本地仓库,并生成一个快照(commit)。
  • git commit 只会提交已经添加到暂存区的文件。如果你想跳过 git add 步骤,直接提交工作区中的文件,可以使用 git commit -a,它会将所有已跟踪的文件(不包括新文件)自动添加到暂存区并提交。

4. 将本地提交推送到远程仓库:git push

  • git push 命令会将本地仓库中的提交推送到远程仓库,通常是将更改推送到如 GitHub、GitLab 或其他 Git 服务器上的共享仓库。

5. 从远程仓库拉取最新代码:git fetchgit pull

  • git fetch:从远程仓库获取新的提交,但不自动合并到当前分支。它只是将远程改动下载到本地,你需要手动合并。
  • git pullgit pull 实际上是 git fetchgit merge 的组合,它从远程仓库获取最新的更改并自动与本地分支合并。

6. 分支管理:git branchgit checkout

  • 创建分支:使用 git branch <branch_name> 可以创建一个新的分支。
  • 切换分支:使用 git checkout <branch_name> 可以切换到指定的分支。
  • 创建并切换分支git checkout -b <branch_name> 命令可以创建并切换到新的分支。

7. 合并分支:git merge

  • 当你在一个分支上完成工作,并希望将其合并到主分支时,可以使用 git merge 命令。
  • git merge 会将另一个分支的更改合并到当前分支。

8. 变基分支:git rebase

  • git rebase 可以将一个分支的更改重新应用到另一个分支上。与 git merge 不同的是,rebase 不会创建新的合并提交,而是将提交历史线性化。

9. 临时保存工作:git stashgit stash pop

  • git stash:如果你在工作区中有未完成的更改,但需要切换到其他分支或执行其他操作,可以使用 git stash 将当前工作保存起来。它会将工作区的更改存储起来,并恢复到干净的状态。
  • git stash pop:当你需要恢复之前存储的更改时,使用 git stash pop 将工作恢复到工作区。

10. 克隆远程仓库:git clone

  • 使用 git clone <repository_url> 命令从远程仓库克隆一个副本到本地。这会将远程仓库的所有内容(包括代码、提交历史等)复制到你的本地机器上。

流程总结:

  1. 本地开发流程
    • 修改代码 → git addgit commitgit push
  2. 从远程仓库获取更新
    • git fetchgit pull → 将远程的更新合并到本地
  3. 分支管理
    • git branch 创建分支 → git checkout 切换分支 → git merge 合并分支
  4. 协作开发流程
    • 先从远程仓库拉取最新代码:git pull
    • 在本地修改代码:git addgit commit
    • 将修改推送到远程仓库:git push
  5. 保存和恢复工作
    • git stash 暂存工作 → git stash pop 恢复工作

1. 状态

1.1 文件状态

image-20240520194220504

2. 分支

2.1 分支常用命令

  • git branch xxx:新建分支
  • git checkout xxx:切换分支
  • git checkout -b xxx:新建分支并切换到该分支(相当于上面两条命令)
  • git branch -d xxx:删除分支
  • git branch:查看分支列表
  • git push origin —delete xxx:删除远程分支
  • git fetch:从服务器上拉取数据,当 git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的数据,它只会获取数据然后让你自己合并。
  • git pull:在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge / git rebase 命令

2.2 分支合并

分支合并主要有两种方式:git merge / git rebase

2.2.1 git merge

git merge 会把两个分支的最新快照以及二者最近的公共祖先进行三方合并,合并的结果是生成一个新的快照(并提交)

工作中的使用流程

现有主分支 master,开发某种功能的分支 dev,dev 上面的内容已经开发完成了,现在要将 dev 分支上的内容合并到 master

  1. git checkout master
  2. git pull(拉取最新代码,也可以使用 git fetch)
  3. git merge dev
  4. … (解决冲突)
  5. git push (提交到服务器)

2.2.2 git rebase

现在同样有主分支 master 与 开发分支 dev,需要将 dev 合并到 master

git rebase 的原理是先找到两个分支(master 与 dev)的最近公共祖先,然后对比 dev 分支对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标分支(master)的最新一次的提交,最后将之前另存为临时文件的修改依序应用

工作中的使用流程

  1. git checkout master(切换到目标分支)
  2. git pull (拉取最新代码)(也可以直接执行 git rebase master dev,省去步骤3和步骤4 )
  3. git checkout dev (切换到开发分支)
  4. git rebase master (执行变基操作)
  5. git checkout master (切换到主分支)
  6. git merge dev (将 dev 分支上的修改变基到主分支)
  7. git push (提交到服务器)

变基操作前的分支图

image-20240520194559107

变基完成后的分支图

image-20240520194644176

无论是 rebase 还是 merge ,整合的最终结果所指向的快照始终是一样的,只不过提交的历史不同罢了。变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起

3. 常用命令

3.1 汇总

git add -i:进入交互式终端模式,可以快速选择某些文件被暂存,达成部分提交的目的。另外该模式下还有多种快捷功能。

git commit —amend:修改最近一次提交的提交信息

git rebase -i:交互式的运行变基,修改多个提交信息(注意无论是 git commit —amend 还是 git rebase -i 都不能涉及到已经推送到服务器的提交)

git revert:撤销(还原)某次提交

3.2 git reset 的不同模式

3.2.1 git reset —soft HEAD~

首先要明白 git 的 “三棵树”,HEAD、Index 以及 Working Directory。

HEAD 是指已经 commit 快照,可以将它看做是 该分支上的最后一次提交

Index 是 “暂存区”,是预期的下一次提交;

Working Directory 是我们自己的工作目录;

我们在工作目录中对文件进行修改,然后添加到暂存区,最后再 commit,HEAD 指向我们最后一次的 commit。

我们运行 git reset —soft HEAD~ 会产生什么效果?下图是我们现在的分支状态和 “三棵树” 的状态

image-20240520195209154

然后我们运行 git reset —soft HEAD~

image-20240520195229458

可以看到,Index 区和 Working Directory 区的状态并没有发生变化,只有 HEAD 指针向前移动了一个节点,git reset —soft HEAD~ 的本质上是撤销了上一次 git commit 命令。当我们运行 git commit 时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交,当将它 reset 回 HEAD~(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变 Index 和 Work Directory。现在可以再次运行 git commit 以达到和 git commit —amend 相同的效果

解释

git reset --soft HEAD~命令会把Git的HEAD指针移动到前一个提交,但是它不会改变索引(index)和工作目录。这就意味着所有的文件改动会被保留,就像你刚刚执行了git add .命令一样。

这里有一个简单的例子来帮助你理解:

  1. 你修改了一些文件。
  2. 你运行git add .命令,把这些改动添加到Git的索引中。
  3. 你运行git commit -m "your message"命令,提交这些改动。

现在,如果你运行git reset --soft HEAD~命令,Git会回退到第2步,也就是说,所有的文件改动都还在,就像你刚刚执行了git add .命令一样。

这个命令在你想要修改最后一次提交的时候非常有用。例如,如果你发现你在最后一次提交的信息中犯了一个错,或者你忘记添加一些文件,你可以使用git reset --soft HEAD~命令回退到git add .,然后再进行提交。

3.2.2 git reset [—mixed] HEAD~

mixed 是 git reset 操作的默认参数,git reset —mixed HEAD~ 可以重置 Index (暂存区)的文件与上次的 commit 保持一致,Work Directory 的内容保持不变。

当我们运行 git reset —mixed HEAD~ 时,reset 会用 HEAD 指向的当前快照的内容来更新索引

git reset —mixed HEAD~ 操作共有两个步骤

  1. 将 HEAD 指针向前移动一个节点,也就是 git reset —soft HEAD~ 操作
  2. 重置 Index (暂存区)的文件与 HEAD 指向的节点保持一致

image-20240520200705837

3.2.3 git reset —hard HEAD~

—hard 是 reset 命令唯一的危险用法,git reset —hard HEAD~ 命令会撤销最后的提交、git add 和 git commit 命令以及 Work Directory 中所有的工作

git reset —hard HEAD~ 总共有三个步骤

  1. 将 HEAD 指针向前移一个节点,也就是 git reset —soft HEAD~ 操作
  2. 重置 Index (暂存区)的文件与 HEAD 指向的节点保持一致,也就是 git reset —mixed HEAD~ 操作
  3. 重置 Work Directory 的文件与 HEAD 和 Index 保持一致

丢失掉最后一次提交。

3.2.4 git reset 的其他用法

git reset file.txt(其实是 git reset —mixed HEAD file.txt 的简写形式),它的实质是将 file.txt 从 HEAD 复制到 Index ,该命令总共有两个步骤:

  1. 移动 HEAD 分支的指向(因为我们给 reset 指定了一个路径,所以它的作用范围限定为指定的文件或文件集合,而 HEAD 只是一个指针,无法让它指向两个提交中各自的一部分,所以该步骤会跳过,HEAD 的指向不变)
  2. 让 Index 看起来像 HEAD

因为 git reset file.txt 会产生 Index 与 HEAD 中 file.txt 文件一模一样的结果,所以 file.txt 会从 Index (暂存区)被移除,git reset file.txt 与 git add file.txt 所做的事正好相反,所以我们可以使用 git reset file_name 来取消暂存一个文件。

我们也可以通过指针一个具体的提交来拉取对应的文件版本,类似于 git reset eb43bf file.txt,这时候再运行 git commit,就会将该版本的 file.txt 提交。

另外,可以使用 git reset —soft HEAD~n 来达到压缩提交的效果

4. git 底层命令

4.1 .git 目录

  • config: 项目特有的配置选项
  • info: 包含一个全局性排除文件,用以放置哪些不希望被记录在 .gitignore 文件中的忽略模式
  • hooks: 包含客户端或服务端的钩子脚本
  • objects: 存储所有的数据内容
  • refs: 存储指向数据(分支、远程仓库和标签等)的提交对象的指针
  • HEAD: 指向目前被检出的分支
  • index: 保存暂存区信息

学习转载自:https://www.cnblogs.com/zhizdk/p/16705578.html