git学习日记
前言:找到一个学习git很方便的网站:https://learngitbranching.js.org/?locale=zh_CN,记录一下学习关键点和总结。
版本节点树
使用git时,要在脑内形成一个版本树,每一个节点都是一个提交记录,有独特的哈希码代表该节点。
分支
分支名可以看作一个指向版本节点的指针。

当前所在分支是main,使用命令:
1 | git branch newImage # 创建一个新分支指向c1提交记录。 |
1 | git checkout newImage # 切换到分支newImage |
简写:
1 | git checkout -b newImage # 创建同时切换分支 |
合并
merge方式合并
将bugFix分支的内容合并到main中,并产生新提交结点,同时main指向新节点。(提交树变复杂,但是不会改变提交历史)
1 | git merge bugFix # 当前在分支main |

此时如何将bugFix移动到与main相同的位置?
1 | git checkout bugFix |
rebase方式合并
变基,就是将本节点及一系列父提交记录复制并粘贴到另一个地方,创造更加线性的提交记录,但是改变了提交树的历史(从提交树上无法得到正确的提交流程)。

1 | git rebase main # 当前在bugFix分支上 以main为基础进行合并 |

提交记录c3仍然存在,合并的同时,提交记录变为线性的。
同理,执行:
1 | git checkout main |
在提交树上移动
HEAD
可以理解为一个指针,指向当前正在处理的提交记录或者分支名。默认下,HEAD指向的都是分支名,但是可以通过checkout指令让它指向提交记录,这就是分离HEAD。

此时 HEAD->main->c1 ,(注意:当HEAD指向分支名时,HEAD等价于该分支名)执行:
1 | git checkout c1 |

这里的c1代表提交记录的哈希值。分离后,git commit不会使main自动指向最新的提交c2,但是HEAD会指向c2。
通过哈希值指定HEAD指向比较困难,一般会使用git log来查看哈希值。哈希值很长,但是只需要写唯一标识提交记录的前几位即可。
相对引用
可以通过^和~两种符号来进行相对引用。
[哈希值|分支名]^ 表示该节点的父节点 (使用~也是相同的)
[哈希值|分支名]~num 表示该节点往上num个节点
[哈希值|分支名]^^^ 表示该节点往上3个节点
特殊:[哈希值|分支名]^num 在当前节点有多个父节点时,默认回到第一个父节点,上述指令则可以通过num选择第几个父节点来回溯
上面的符号支持链式操作。
强制修改分支位置
1 | git branch -f main HEAD~3 # 让main强制指向HEAD的第三个父节点 |
撤销变更
reset:在本地让分支指向回退版本
1 | git reset HEAD^ |
但是这样只能在本地使用,不能分享到远端。此时使用revert
revert:在本地创建新提交,该提交与某个历史版本相同。
1 | git revert HEAD^ |
整理提交记录
cherry-pick:选定某些提交复制到当前位置(HEAD)下面

1 | git cherry-pick c2 c4 |

rebase -i :当不清楚提交的哈希值时,使用交互式rebase整理提交
1 | git rebase -i [结束整理的节点\产生分支的节点] |
执行命令会导致出现交互式窗口,然后从当前节点到指定节点的一系列提交都可以选择和排序,然后git复制处理后的一系列节点到指定节点下(整理并复制之前的提交,产生新的一系列提交)。
历史提交记录不能直接修改,需要移动为最新提交(没有子孙节点)然后再修改
远程操作
1 | git clone [远程仓库地址] # 复制一个相同的仓库到本地,同时在本地创建同名分支和一个同名远程分支 |
远程分支命名:[remote name/branch name],remote name往往是origin
若执行:
1 | git checkout origin/main # 自动分离HEAD,因为本地的远程分支是远程仓库中该分支的镜像,时只读的 |
git fetch

1 | git fetch (无参数,下载远程仓库所有分支更新到本地的每一个对应远程分支) |

可以看到:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(如
o/main) - 本地的main分支没有更新
1 | git fetch [remote] [place] |
git fetch + git merge = git pull
在fetch基础上:
1 | git merge origin/main #更新本地main分支 |
1 | git pull # 一步完成以上步骤 |
git pull的参数可以看作提供给了git fetch和git merge。
1 | git pull origin foo 相当于: |
git push
- 将本地与远端对应的分支推送到远端,更新远端的同时,将本地在远端分支的镜像也更新
即:将main分支推送并更新远端,本地的origin/main也更新。
1 | git push [remote] [place] |
仅使用git push也可以,但是要保证当前工作分支是要push的分支。

1 | git push origin foo^:main |

如果目标分支不存在,则在远端创建一个对应名称的分支。
没有指定source时
1 | git push origin :foo # 会导致远程仓库中的foo分支被删除 |
冲突的工作
设想以下场景:假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是你的同事这周写了一堆代码,还改了许多你的功能中使用的 API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。
这时你怎么将自己的改动push上去?
- 先将更新拉取下来并合并到本分支
- 然后将结果push到远端
1 | git fetch |
远程服务器拒绝 要求pull request
远程仓库拒绝直接将改动push到main,多见于提交别人的仓库时,别人不想你随便改动他的仓库,他希望控制权在自己手中,于是设置了pull requist。此时你不能将改动直接push到对方已存在的分支上。
解决:新建一个分支fix并提交,将合并的权力交给对方。然后将本地的main分支reset到origin/main的位置,防止产生冲突。
跟踪远程分支
远程分支需要与本地分支进行绑定,然后才能使用fetch pull push等指令进行交流。clone时会默认生成本地分支并绑定,名称往往是相同的。
如何自己指定某个本地分支与远程绑定?
- 创建一个newMain 跟踪远程分支o/main
1 | git checkout -b newMain o/main |
- 使现有分支追踪远程分支
1 | git branch -u o/main foo # 如果当前就在foo上,还可以省略foo |
- Title: git学习日记
- Author: HangYF
- Created at : 2025-02-20 17:32:59
- Updated at : 2025-02-20 17:35:06
- Link: https://redefine.ohevan.com/2025/02/20/git学习日记/
- License: This work is licensed under CC BY-NC-SA 4.0.