image-20240611164552505

github 上的仓库(remote)

仓库的主分支 main (原来叫 master )

假设这个 main branch 上只有一个 commit 是 init

当我们想修改代码/贡献代码的时候,第一件事就是将 remote 仓库复制到本地。

image-20240611164121679

git clone <仓库地址>

# 其中 local 可以当作是 local git(本地仓库)
# disk 是磁盘,这部分是源文件真正在磁盘里的样子,当我们刚进行 clone 的时候,remote、local、disk 都是一样的。

修改代码

image-20240612133642690

# 在我们需要修改代码的时候,首先就是建立一个 branch
# 建立一个 branch 会有很多好处,最重要的是不会让你的 主分支 代码不能工作
# 建立自己的 branch 对应的命令, 该命令会复制一份branch到你的新branch上。
# 当我们新建一个 branch 时,git会把这个branch上的所有文件同步给硬盘,这时硬盘里边保存的所有源代码都是志这个branch 的代码。
git checkout -b my-feature

image-20240612135120236

# 当我们修改代码的时候,硬盘上的文件是有变化的。但是git对此一无所知。
# 这时可以使用 diff 命令查看硬盘上的文件和我git中的分之有什么变化。

image-20240612135405130

# 当我们把修改的文件告知git的时候,可以使用 git add 命令。
# git add 的参数就是文件名。可以将所有修改的文件放到 git add 命令后边。
# 这个命令会把所有修改的文件放到一个暂存区里边去。这个时候,git就知道我们到底修改了那些文件。
# 当我们需要将这些修改的文件提交到 git 上时,可以使用 git commit 命令。

image-20240612135759192

s
# 当我们使用 git commit 时,git就会新增加一个 commit

image-20240614093744372

# 这个时候就可以看出 feature branch 已经和 main branch 已经不一样了。
# 现在我们做了 commit ,改变只是存在 local git 中,remote 仓库其实是不知道的。

image-20240614094450096

# 这个时候我们可以用 git push origin my-feature 命令去 push 
# 使用这个命令之后,我们就会发现 github 上多处来了一个 branch:my-feature ,这个分支里边保存着我们做的改动。

image-20240614094732338

# 我们经常会遇到的情况是,当我们push上去的时候,main branch 又有更新了。
# 所以我们要测试一下我的这个feature在新的update更新之下是否还好使。
# 所以我们要把 main 这个 branch 的更新同步到我们的这个 my-feature 里。
# 接下来我们首先要更新我们的 local branch,因为目前我们 local 中的 main 和 remote 中的 main 是不一样的。

image-20240614095150946

git checkout main  # 切换到 main 这个分支里边。
# 其实这个时候,我们硬盘里的源代码其实是 init 的状态,并不是刚才我们修改的状态。

image-20240614095356917

git pull origin master # 把远端的 main 同步到我的 local 中的 main 中。
# 做完上面这步操作,远端的github上的 update 这个 commit 就会同步到我的 local git 中和我的 disk 上

image-20240614100111839

# 然后我们要回到 my-feature 上
git checkout my-feature # 当前的代码是有我们修改的 f-commit 的变化,没有远端 update 的变化。

image-20240614100302909

git rebase main # 把我的修改先都扔到一边,然后把main最新的修改拿过来,在这个基础之上再把我的修改尝试放上去
# 在这个过程中有可能会 rebase conflict ,如果出现了这种情况,就需要我们手动选择我们要哪一段代码。
# 在 rebase 成功之后,我们的 feature branch 就变成了 init update f-commit 这种情况
# 其实在 rebase 成功之后,我们相当于在最新的 main update 之上,做了我们的修改 f-commit,这就是使用 rebase 而不是用 merge 的好处。

image-20240614100821042

# 在更新完我们的 feature branch 之后,我们需要 git push -f origin my-feature
# 把我们 local git 里面这个 branch push 到 github 上
# 这里需要注意,由于我们做了这个 rebase ,所以我们在 push 的时候,需要加上 -f 选项。

image-20240614101104233

# 到此我们就要把我们更新的代码,合并到这个main branch里面了
# 这个过程我们教 pull request
# 为什么要叫 pull request 呢?因为我们形式上认为这个主分支是属于项目的不属于任何个人,
# 而功能分支,也就是所谓的feature branch是属于个人的,尽管这个 feature branch 的主人和这个项目的主人
# 可能是一个人,但在这两个分支上他们是不同的角色,pull request的意思是request这个项目的主人把我这个新的分支的改变给pull到这个项目里去,

image-20240614101537949

# main brach 的维护者,在审查了你的代码之后,一般情况下会用 squash and merge 
# 为什么会做 squash 操作:在我们这个例子里 my-feature 这个 branch 只有一个 commit,但是在更多的情况下,我们的功能分支上面的 commit 是比较乱的,有可能有很多代码格式的改变啊有很多bug fix啊, 我们不希望把这些 commit,每一个都放到我们的 main branch 里面,我们希望我们 main branch commit history 尽可能的简洁,尤其我们希望我们的 main branch 里面,每一个 commit 都是正常工作的,所以在大多数情况下面对 pull request 我们会选择 squash and merge 。
# squash and merge的意思就是:把这一个分支上面的所有改变合并成一个改变,然后把这个commit给放到我的main branch上,也就是这些改变可能变成了update2 这个commit,你的代码改动都被正常的合并到了main branch里面,只是commit的结构数量和名字改变了,那在pull request被merge之后,我们就会把远端的这个branch直接删掉,在github上有一个按钮啊叫delete branch,

image-20240614102154454

# 远端的那个 my-feature 被删除掉了,但是我们 local git 上还有
# 这个时候需要切换到 main branch 上
git checkout main

# 然后使用
git branch -D my-feature # 删除 local git 中的 my-feature branch

image-20240614102542386

# 最后再拉取一次 远端的 main update2 ,拉到我们的 local main branch 和 disk 上。
git pull origin master

# 经过这些操作之后,我们的 remote 、local、disk 又都一样了。

在任何有规模的项目里边,不管是开源的还是公司自己的,都会使用比较正规的工作流。正如本文所讲的一样,它们都是适用的。