Git笔记(37) 替换

  • 1. 替换
  • 2. 举例

1. 替换

之前强调过,Git 对象数据库中的对象是不可改变的
然而 Git 提供了一种有趣的方式来用其他对象 假装 替换数据库中的 Git 对象

replace 命令可以让你在 Git 中指定某个对象并告诉 Git:“每次遇到这个 Git 对象时,假装它是其它对象
在用一个不同的提交替换历史中的一个提交而不想以 git filter-branch 之类的方式重建完整的历史时
这会非常有用


2. 举例

例如,有一个大型的代码历史并想把自己的仓库分成一个短的历史和一个更大更长久的历史
短历史供新的开发者使用,后者给喜欢数据挖掘的人使用
可以通过用新仓库中最早的提交“替换”老仓库中最新的提交来连接历史
这种方式可以把一条历史移植到其他历史上

这意味着不用在新历史中真正替换每一个提交(因为历史来源会影响 SHA-1 值),你可以加入他们

首先获取一个已经存在的仓库,并将其分成两个仓库,一个是最近的仓库,一个是历史版本的仓库
然后我们将看到如何在不更改仓库 SHA-1 值的情况下通过 replace 命令来合并他们

将使用一个拥有 5 个提交的简单仓库:

$ git log --oneline
ef989d8 fifth commit
c6e1e95 fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit

想将其分成拆分成两条历史
第一个到第四个提交的作为第一个历史版本
第四、第五个提交的作为最近的第二个历史版本


创建历史版本的历史很容易,可以只将一个历史中的分支推送到一个新的远程仓库的 master 分支

$ git branch history c6e1e95
$ git log --oneline --decorate
ef989d8 (HEAD, master) fifth commit
c6e1e95 (history) fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit


现在可以把这个新的 history 分支推送到我们新仓库的 master 分支:

$ git remote add project-history https://github.com/schacon/project-history
$ git push project-history history:master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (12/12), 907 bytes, done.
Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
To git@github.com:schacon/project-history.git* [new branch]      history -> master

这样一来,我们的历史版本就发布了
稍难的部分则是删减我们最近的历史来让它变得更小

需要一个重叠以便于用一个相等的提交来替换另一个提交
这样一来,我们将截断到第四、五个提交

$ git log --oneline --decorate
ef989d8 (HEAD, master) fifth commit
c6e1e95 (history) fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit

在这种情况下,创建一个能够指导扩展历史的基础提交是很有用的
这样一来,如果其他的开发者想要修改第一次提交或者其他操作时就知道要做些什么
因此,接下来我们要做的是用命令创建一个最初的提交对象
然后将剩下的提交(第四、第五个提交)变基到它的上面

为了这么做,我们需要选择一个点去拆分,对于我们而言是第三个提交(SHA 是 9c68fdc
因此我们的提交将基于此提交树
我们可以使用 commit-tree 命令来创建基础提交
这样我们就有了一个树,并返回一个全新的、无父节点的 SHA-1 提交对象

$ echo 'get history from blah blah blah' | git commit-tree 9c68fdc^{tree}
622e88e9cbfbacfb75b5279245b9fb38dfea10cf
Note

commit-tree 命令属于底层指令 有许多指令并非直接使用,而是被其他的 Git 命令用来做更小一些的工作
有时当我们做一些像这样的奇怪事情时,它们允许我们做一些不适用于日常使用但真正底层的东西


现在已经有一个基础提交了,可以通过 git rebase --onto 命令来将剩余的历史变基到基础提交之上
--onto 参数是刚才 commit-tree 命令返回的 SHA-1 值
变基点会成为第三个提交(我们想留下的第一个提交的父提交,9c68fdc):

$ git rebase --onto 622e88 9c68fdc
First, rewinding head to replay your work on top of it...
Applying: fourth commit
Applying: fifth commit


我们已经用基础提交重写了最近的历史,基础提交包括如何重新组成整个历史的说明
我们可以将新历史推送到新项目中,当其他人克隆这个仓库时
他们仅能看到最近两次提交以及一个包含上述说明的基础提交

现在将以想获得整个历史的人的身份来初次克隆这个项目
在克隆这个截断后的仓库后为了得到历史数据
需要添加第二个远程的历史版本库并对其做获取操作:

$ git clone https://github.com/schacon/project
$ cd project$ git log --oneline master
e146b5f fifth commit
81a708d fourth commit
622e88e get history from blah blah blah$ git remote add project-history https://github.com/schacon/project-history
$ git fetch project-history
From https://github.com/schacon/project-history* [new branch]      master     -> project-history/master

现在,协作者在 master 分支中拥有他们最近的提交并且在 project-history/master 分支中拥有过去的提交。

$ git log --oneline master
e146b5f fifth commit
81a708d fourth commit
622e88e get history from blah blah blah$ git log --oneline project-history/master
c6e1e95 fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit

为了合并它们,可以使用 git replace 命令加上你想替换的提交信息来进行替换
现在就可以将 master 分支中的第四个提交替换为 project-history/master 分支中的“第四个”提交

$ git replace 81a708d c6e1e95

现在,查看 master 分支中的历史信息,显示如下:

$ git log --oneline master
e146b5f fifth commit
81a708d fourth commit
9c68fdc third commit
945704c second commit
c1822cf first commit

不用改变上游的 SHA-1 我们就能用一个提交来替换历史中的所有不同的提交
并且所有的工具(bisect,blame 等)也都奏效


有趣的是,即使是使用了 c6e1e95 提交数据来进行替换,它的 SHA-1 仍显示为 81a708d
即使你运行了 cat-file 命令,它仍会显示你替换的数据:

$ git cat-file -p 81a708d
tree 7bc544cf438903b65ca9104a1e30345eee6c083d
parent 9c68fdceee073230f19ebb8b5e7fc71b479c0252
author Scott Chacon <schacon@gmail.com> 1268712581 -0700
committer Scott Chacon <schacon@gmail.com> 1268712581 -0700fourth commit

请记住,81a708d 真正的父提交是 622e882 占位提交,而非呈现的 9c68fdce 提交

另一个有趣的事情是数据将会以以下引用显示:

$ git for-each-ref
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/heads/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/remotes/history/master
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/HEAD
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/replace/81a708dd0e167a3f691541c7a6463343bc457040

这意味着我们可以轻而易举的和其他人分享替换
因为我们可以将替换推送到服务器中并且其他人可以轻松地下载
也许在历史移植情况下不是很有用,但在其他情况下仍然很有用


参考: git
以上内容,均根据git官网介绍删减、添加和修改组成


相关推荐:

Git笔记(36) 打包
Git笔记(35) 子模块
Git笔记(34) 调试
Git笔记(33) Rerere
Git笔记(32) 高级合并


谢谢

Git笔记(37) 替换相关推荐

  1. Git笔记(38) 凭证存储

    Git笔记(38) 凭证存储 1. 凭证存储 2. 底层实现 3. 自定义凭证缓存 1. 凭证存储 如果使用的是 SSH 方式连接远端,并且设置了一个没有口令的密钥 就可以在不输入用户名和密码的情况下 ...

  2. 【Git笔记3】关于撤销、删除、恢复的那些事儿

    在跻身于"国庆抢票大战"的我们,不要忘记学习,今天接着上篇 [Git笔记2]必知习惯和如何版本回退,继续开干!一起来瞅瞅如何撤销没有add的修改,如何撤销以及add到暂存区的修改, ...

  3. Git笔记(32) 高级合并

    Git笔记(32) 高级合并 1. 合并冲突 1.1. 中断一次合并 1.2. 忽略空白 1.3. 手动文件再合并 1.4. 检出冲突 1.5. 合并日志 1.6. 组合式差异格式 2. 撤消合并 2 ...

  4. Git笔记(31) 重置揭密

    Git笔记(31) 重置揭密 1. 三棵树 1.1. HEAD 1.2. 索引 1.3. 工作目录 2. 工作流程 3. 重置 3.1. 移动 HEAD(--soft) 3.2. 更新索引(--mix ...

  5. Git笔记(23) 不同角色的贡献

    Git笔记(23) 不同角色的贡献 1. 私有小型团队 2. 私有管理团队 3. 派生的公开项目 4. 通过邮件的公开项目 1. 私有小型团队 可能会遇到的最简单的配置是有一两个开发者的私有(闭源)项 ...

  6. 任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记37

    任务切换的方法--<x86汇编语言:从实模式到保护模式>读书笔记37 1. 中断门和陷阱门 在实模式下,内存最低端的1M是中断向量表,保存着256个中断处理过程的段地址和偏移.当中断发生时 ...

  7. 【Git笔记2】必知习惯和如何版本回退

    良好的习惯会让工作和生活如鱼得水,在使用git的时候有些必知习惯和概念你要get一下,总有些许失误,如:已经提交了不合适的修改到版本库时还没有把自己的本地版本库推送到远程,想要撤销本次提交,或者已经p ...

  8. git 32位_完整的GIT笔记 快速上手小白教程

    GIT 是什么? Git 是目前世界上最先进的分布式版本控制系统.并且它是一个免费的.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. 什么是版本控制系统 版本控制是一种系统,它跟踪一 ...

  9. Git笔记(36) 打包

    Git笔记(36) 打包 1. 打包 2. 举例 1. 打包 虽然我们已经了解了网络传输 Git 数据的常用方法(如 HTTP,SSH 等) 但还有另外一种不太常见却又十分有用的方式 Git 可以将它 ...

最新文章

  1. pygame的学习以及python的巩固(窗口尺寸的显示)
  2. C# 使用AggregateException 信息
  3. young people can also be a leader
  4. Spring Boot + Spring Data + Elasticsearch实例
  5. Winform导入文件
  6. java中的静态块static{}及this,super,final的用法总结
  7. 【转载】在回答WCF问题时,在我们的园子找到了一篇彪悍的文章
  8. 青岛宏大FA231梳棉机触摸屏(三菱)程序,也有改造用台达触摸屏(DOP-AS57BSTD
  9. 很多的计算机英语词汇是通过,计算机英语词汇隐喻分析
  10. U盘中毒后被隐藏的文件夹无法隐藏选项无法取消
  11. 微前端框架 之 single-spa 从入门到精通
  12. 安装科来-csnas_tech_12.0.5.12506_x64
  13. 【PyTorch】关于函数 datasets.IMDB.splits()
  14. Stream流和Optional
  15. 【OSPF外部路由-4类LSA(sum-asbr)和5类LSA(external)以及7类LSA(Nssa)】(OSPF的特殊区域)(外部路由选路特性)
  16. vim 重新编译,支持lua (compile vim with lua)
  17. JAVA垃圾分类管理系统-含论文基于SSM【数据库设计、毕业设计、源码、开题报告】
  18. 标签上的 title属性与 alt属性的区别
  19. [ 数据结构-C语言 ] 二叉树--初阶 大总结~~
  20. 查看nginx服务器状态

热门文章

  1. topshelf和quartz内部分享
  2. Sql Server 字段类型说明
  3. Finalize,Dispose,SuppressFinalize
  4. PowerDesigner逆向工程,从数据库导出PDM(包括采坑记录)
  5. Spring Boot系列教程五:使用properties配置文件实现多环境配置
  6. 面试必备TCP三次握手
  7. 说说我心中的Linux系统
  8. 迟到的 cocoapod 版本适配 之网利宝
  9. sccm 2007 r2 step by step 之十五 补丁管理
  10. Android常见漏洞