Mastodon | 以 local-only 代码合并为例浅谈如何合并特定 commit
2022-4-21 Update:
给大家提供了更方便的方法,现在可以直接使用这个链接给你的代码提pr,v3.5.1可以无痕merge。登陆你的账号并把base repository改为你的提交即可。
前言
本文会尽我可能解释涉及到的所有概念,但还是推荐有一定的 git 使用基础后阅读。推荐阅读的前置内容:《如何利用Docker搭建Mastodon实例(二):进阶魔改篇》 的升级章节。
最初是有一位大神写了 local-only 的功能,可以让嘟文限制在本实例而不流出外部。此 pr 并没有被官方采纳,但是一些站点都有增加这个魔改功能。
本篇以我的 local-only commit ( 需要改个bug )为例,说明如何合并这种代码量较大的魔改(代码量小的通常找到位置复制粘贴即可,参考文章开头的教程 )。
从远程仓库拉取代码
首先将你的代码仓库 git clone
到本地,或直接 cd
到已有的仓库目录:
1 | $ git clone https://github.com/yourname/mastodon.git |
此时如果查看远程连接情况,只会看到一个名为 origin
的远程仓库链接,也就是你自己的远程仓库的名字。
1 | $ git remote -v |
此时如果查看分支情况,一般而言默认是只 clone
了 main
分支(即 origin/main
)。
1 | $ git branch -vv |
(可选)创建一个专门用于处理此次合并的分支
如果你熟悉 git
的分支管理,此时可以新建一个专门的分支,最后再并入主干,本文采取直接合入主干的方式,故这部分不展开讲。
设置远程仓库连接
一个基础的 git
概念是,在本地的这个是你的本地代码仓库,而 GitHub 只是代码的远程托管,本地和远程仓库可以理解为一个仓库的两个副本,你可以把你的代码发送给远程仓库,也可以从远程仓库拉取,而且一个本地仓库可以连接不止一个远程仓库。
现在添加我的 local-only 的仓库 作为 upstream
:
1 | $ git remote add upstream https://github.com/retirenow/mastodon.git |
此时再查看远程连接:
1 | $ git remote -v |
就会有两个远程,名字分别为 origin
和 upstream
。
拉取分支并合并代码
设置好远程以后,我们就可以从 upstream
拉取含有 local-only 的分支:
1 | $ git fetch upstream main:instance_only_statuses |
这边因为分支都叫 main
,为了区分我给从 upstream
拉取的本地分支重命名了一下。上面这句话的意思是,从 upstream
拉取它的 main
分支,并命名为本地的 instance_only_statuses
。
这时候查看分支情况,会有两个分支:
1 | $ git branch -vv |
星号代表你现在处于 main
分支上。
现在 cherry-pick 这个 commit:
1 | $ git cherry-pick 6a2ca72f711849586f49c44dde555abb0ad13179 |
那一长串编码是这个 commit
的哈希值,可以唯一指定找到这串 commit
,可以在 commit
页面找到。
cherry-pick
用于只合并特定 commit
,和 merge
类似,merge
是合并两个分支(包含所有 commit
)。
处理冲突
在 cherry-pick
之后,如此大的改动量通常会提示代码有冲突,推荐用 vscode 处理。
从侧边的 git
点进去看:
其中暂存的更改(Staged Changes)就是已经被自动合并好的代码,不需要处理,而合并更改(Merge Changes)则是需要处理的冲突文件,具体数量因人而异。
点开合并更改中一个文件,在冲突的地方,会有如下所示:
Accept Current Change 是保持现在(main分支)的代码,Accept Incomming Change 是用 local-only 的代码,Accept Both Changes 则是保留两者。
这里的处理其实需要一点灵性和连蒙带猜,可以结合原始pr的file change理解一下它增加代码的逻辑然后去选择如何更改。以上图为例,显然是因为我们main分支增加了一个叫 “ordered_media_attachment_ids” 的东西,而 local only 也增加了 “local_only”,所以我们的选择就是 Accept Both Changes。
处理完冲突后
一般而言,如果你是参考这个教程进行代码魔改,此时你只需要提交你的改动:
1 | $ git add . |
然后静待 GitHub 编译好镜像,你再拉取使用即可。
我在这一步遇到了报错500,参考这篇文章对数据库进行 migrate 再重启即可。
在 docker 容器中 debug
但是通常来说如此大的代码改动量,有一定风险不能一次性跑通,如果直接使用镜像遇到问题,我推荐参考《Docker 部署的 mastodon 在容器内 debug》。或者如果不放心也可以先在容器内部编译通过再拉取镜像。
首先进入 docker 容器:
1 | $ docker exec --user root -it mastodon_web_1 /bin/bash |
容器里默认是没有 git
的,需要先安装 git
:
1 | $ apt-get update |
这时候可能会遇到报错
1 | E: Archives directory /var/cache/apt/archives/partial is missing |
解决方案:
1 | $ mkdir -p /var/cache/apt/archive/partial |
继续:
1 | $ apt-get install git |
即可正确安装。
进入到我们的代码目录:
1 | $ cd /mastodon |
然后添加你的远程仓库并拉取最新的代码:
1 | $ git remote add origin https://github.com/yourname/mastodon.git |
也可以一开始就直接在 docker 容器里合代码,如果你会用 vscode 连接 docker 容器,原理都是一样的。
接下来 precompile:
1 | $ RAILS_ENV=production bundle exec rails assets:precompile |
通过后退出并 docker-compose restart
,就可以直接在网页上预览效果了。