Git
就是只有一份文件,通过分出不同的分支,不同分支上提交的文件只在对应分支可见,完成功能后的分支可以合并到主分支上,完成功能的分支可以选择被删除
软件配置管理 Software Configuration Management 软件配置管理(SCM)是指通过执行版本控制、变更控制的规程,以及使用合适的配置管理软件,来保证所有配置项的完整性和可跟踪性。配置管 理是对工作成果的一种有效保护。
提交一个文件创建了三个版本号
第一个版本号指向了状态信息版本号?
状态信息版本号指向文件版本号?
文件版本号指向文件内容
parent 指向上一次的提交信息
删除文件
紫色代表删除的状态
文件在 git 中并没有真正被删除,只是不指向
head 中指向了 main记录了最新的文件
分支只是产生了新的不同提交,不同分支引用了不同文件,并没有备份
分支会提取对应分支版本的文件
GitSource
检出
: 切换到所在位置提交时文件的状态
重置当前分支到此次提交
: 将本地文件恢复到这次提交,之后改动的文件全部放到暂存区域
软合并-保持所有本地改动,文件会出现在已暂存文件
混合合并-保持工作副本但重置索引,文件会出现在未暂存文件
强行合并-丢弃所有工作副本改动
- 快进(Fast-forward):在Git中,当你合并分支时,如果被合并的分支的所有新提交都是建立在目标分支最新提交之上的,Git会执行一种叫做"快进"的合并方式。这意味着Git只需简单地将目标分支指针直接指向被合并分支的最新提交,从而合并完成。在这种情况下,没有实际的合并操作发生,因为目标分支并没有发生变化,只是指向了被合并分支的最新提交。这种合并方式保持了提交历史的线性整洁性。
title:简介
Git
git check
git checkout -b feature c2
在指定位置创建分支并检出
git branch x
x 为位置,没有为当前检出位置添加分支
git branch -f x y
强行制定 x 到 y 处
git merge
另一个分支--> 融入
-->当前分支
git merge
让另外一个分支或指定 HEAD
融入到自己的分支
git checkout main
git merge other
让其他线程融入自己
git rebase
变基
git rebase x
当前分支 y--> 依靠
-->另一个分支 x
git rebase x y
y 依靠到 x 上,相当于 y 获得所有 x 的更改
git rebase
: 相比 merge
会创造更线性的提交历史, Rebase
实际上就是取出自己的一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。使得代码演变过程更容易理解和跟踪。特别是在长时间开发的分支中,rebase
可以帮助保持提交历史的清晰度。
在公共仓库中,尤其是已经共享的分支上,应尽量避免使用 rebase,因为它会重写提交历史,可能导致其他开发者的工作产生冲突。
当前分支 rebase
另一个分支
Head
Head
: HEAD 是一个对当前所在分支的符号引用
,也就是指向你正在其基础上进行工作的提交记录。HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。
HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见
git checkout head
后可以进行 git commit
,但不属于任何一个分支
相对引用:查看
- 使用
^<num>
指向当前提交的父提交,数字代表选择哪个父提交 - 使用
~<num>
向上移动多个提交记录,如HEAD~3
,向上移动 3 个 - 链式操作
~<num>或^<num>
之间随意组合,如
parent
(父提交)指的是一个提交的直接 前一个提交
,想要在提交树中自由移动则使用上面的 HEAD^<num>,HEAD~<num>
main
有两个 parent
提交,为c1
和c2
^数字
当前提交的某个 parent
提交
git checkout 具体head
可以一直使用 HEAD^
向上移动
git checkout HEAD^
git checkout HEAD^
git checkout HEAD~
相对引用:移动
git branch -f 分支 HEAD~2
对于该分支提交过的前两个
git branch -f 分支 另一个head
(可以为分离式 head)强制到具体分支,即使不是该分支提交
后面的提交会被舍弃变成 分离式head
撤销变更/重置提交 reset
不能在分离式 head 中使用
git reset HEAD
HEAD
可以是 HEAD,HEAD^,HEAD~x,或特定head
对远程分支无效
本地分支使用 reset
因为 reset 会造成历史记录不同
回滚提交 revert
git revert HEAD
远程分支使用 revert
-
git revert HEAD
: 使用git revert HEAD
命令会撤销当前分支上最新的提交(即 HEAD 指向的提交)。这意味着将会撤销最近一次的提交,并创建一个新的提交来保存撤销的更改。 -
git revert HEAD^
: 使用git revert HEAD^
命令会撤销当前分支上倒数第二个提交(即 HEAD 指向的提交的父提交)。这样会撤销倒数第二次的提交,并创建一个新的提交来保存撤销的更改。
git rebase c2
git reset c5
磷选 git cherry-pick
是复制了一份,比之前多了一份
复制到当前的 head
位置下
git cherry-pick 1 2 3 4
当前分支复制其他分支内容
- 通常用于提取固定的记录
其他分支遇到 bug
后,需要调试可能包括很多步骤,同步到主分支会包含很多不必要的信息,只需要最后解决问题的步骤同步到著代码即可
交互式变基 rebase
git rebase -i HEAD~4
可以对之前的某次提交删除,更改顺序
用此前的 squash,将两次修改合并,但是这两次修改不能有同一个文件,否则报错
git commit --amend
修改上一次提交,当需要修改某一次提交时
Tag
git Tag Tag_name Head名
不指定 head 则为当前的
分支很容易被改变,大部分分支还只是临时的,并且还一直在变。
有没有什么可以_永远_指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法
就是 Tag
git describe
git describe
: 输出 tag_距离_分支
其他
title:简介
git rebase c13 将自己独有的一个一个复制到指定的位置后
git branch -f main c13 是强制到指定的位置,自己独有的都抛弃了
title:多个分支合并到main分支
每次合并肯定合并到最新的代码上,分支合并完后,最后再将主分支合并到最新的地方
直接merge的形式,但没有rebase更容易理解和跟踪,但此时分支没有变化,只变化了主线程
远程
<remote name>/<branch name>
如 origin/main
在远程分支提交会变成分离式 head
fetch
-
git fetch
下载远端所有分支到本地远程分支
-
git fetch origin foo
指定获取远程的 foo 分支,到本地的远程分支 -
git fetch origin <source>:<destination>
source
远端
destination
本地 -
git fetch origin :bar
fetch 空,会在本地创建个新分支bar
pull
只能在本地远程分支上用,而 fetch
可以直接用
如果该分支没有和远端对应的跟踪,则不能进行 pull
pull --rebase == fetch-->rebase
pull == fetch-->merge
git pull <source>:<destination>
source
远端
destination
本地, 没有会创建
拉取指定分支
本地分支和本地远程分支一致时,使用两者没有区别
title:区别
pull
pull --rebase
本地分支和本地远程分支一致时,使用两者没有区别
git pull
是 git fetch
和 git merge
的合并
先把远程的更新下载下来,再和自己本地的合并
git cherry-pick o/main
git rebase o/main
git merge o/main
title:流程
该教程左边本地
git fetch
git merge o/main
或直接git pull
冲突
远程仓库的文件在两个远程被修改,
此时一个推送,另一个推送会拒绝
先 merge 或 rebase 后再 push
title:简介
git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks push -v origin main:main
Pushing to https://github.com/XCJYO/Subconvert
To https://github.com/XCJYO/Subconvert
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/XCJYO/Subconvert'
hint: Updates were rejected because the remote contains work that you do not hint: have locally. This is usually caused by another repository pushing to hint: the same ref. If you want to integrate the remote changes, use hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
这是因为远程仓库包含了本地仓库中没有的更新
hint翻译为引用
完成时带有错误,见上文。
此时一个推送,另一个获取会
用变基解决
自己当时拉取的代码现在变旧了
直接在新代码的基础上添加你的代码,亦或由于你的提交已经过时而直接忽略你的提交?
因为这情况(历史偏离)有许多的不确定性,Git 是不会允许你 push
变更的。
也就是远程仓库被别人修改了,你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了,提交可能被拒绝
pull --rebase==fetch-->rebase
pull==fetch-->merge
title:简介
此时git push会失败
可以通过rebase调整工作
requeset
你应该按照流程, 新建一个分支, 推送 (push)这个分支并申请 pull request, 但是你忘记并直接提交给了 main. 现在你卡住并且无法推送你的更新.
新建一个分支feature
, 推送到远程服务器. 然后reset
你的main
分支和远程服务器保持一致, 否则下次你pull
并且他人的提交和你冲突的时候就会有问题.
title:多分支合并提交
先拉去远端分支
然后分支变基本地远程分支
然后其他分支依次变基
最后本地main变基
远程跟踪
git checkout -b x o/main
跟踪远程分支, 自动创建分支
git branch -u o/main foo
跟踪远程分支
就是 main
和 o/main
进行了关联,这种关联就是远程跟踪,mian
被设置为跟踪,克隆的时候,就已经设置好了
进行 pull
时,更新到 o/main
然后自动更新 main
进行 push
时,更新到远程 main
, 同时更新 o/main
如果该分支没有和远端对应的跟踪,则不能进行 pull
可以让任意分支跟踪 o/main
, 然后该分支会像 main
分支一样得到隐含的 push 目的地以及 merge 的目标。这意味着你可以在支 totallyNotMain
上执行 git push
,将工作推送到远程仓库的 main
分支上。
push
-
git push <remote> <place>
将指定分支推送到远端,并建立了跟踪 -
git push origin(固定) <place>
-
git push origin <source>:<destination>
<source>
本地,可以为head
destination
远程,不存在的话远端则会自动创建
可以将本地指定分支或 head 推送到远端指定的分支 -
git push origin :foo
推送空的, 删除了远端foo
分支
切到本地仓库中的“place”分支,获取所有的提交,再到远程仓库“remote”中找到“place”分支,将远程仓库中没有的提交记录
都添加上去,搞定之后告诉我。
如果直接 git push
git push origin <source>:<destination>
destination
不存在的话远端则会自动创建
总结
操作远程分支喜欢用 rebase
而不是 merge
但 merge
能保留修改树的历史
喜欢更干净的提交树就用 rebase