我正在做一个项目,我们想编辑 Twitter Bootstrap 附带的 LESS 文件。 standard advice是让这些文件保持不变,以便更容易升级 Bootstrap。但是这个建议对我们不起作用;我们的代码变得脆弱且难以维护。
似乎应该可以通过 git 子树 merge 来解决这个问题:我们可以编辑 Bootstrap 的 LESS 文件以获得清晰、可维护的代码,然后使用 git 的 merge 工具引入新版本的 Bootstrap。
我们已经提出了使用子树 merge 的计划。但在我们将计划付诸实现之前,我想得到一些反馈:是否有我们忽略的重大缺陷?有更好/更简单的方法吗?
有重大缺陷的方法
在simplest approach对于子树 merge ,来自子树(即 Bootstrap)的所有提交都被 merge 到项目的 master
分支中。缺点是 Bootstrap 有太多的提交,我们的提交在噪音中迷失了。我们想让他们的提交远离我们的 master
分支。
理论上,我们可以使用 git rebase -i
将所有 Bootstrap 提交压缩为一个提交,然后我们将其 merge 到 master
中。但是 rebase -i
does not work well with merges .
@Sigi helpfully suggested我们使用 squash merge 从 bootstrap-upstream
到 master
。抓取初始版本的 Bootstrap (v3.1.0) 工作正常。但是当我们在下一个版本(v3.1.1)中 merge 时,我们有超过 100 个 merge 冲突。 3.1.0 和 3.1.1 之间的每个 Bootstrap 更改都被标记为冲突。 (我们的确切步骤在 this gist 中。)
计划
我们的计划是使用一个分支,merge-from-bootstrap
,将 Bootstrap 提交 pull 入我们的存储库。当 merge 更改 in 到 merge-from-bootstrap
(我们对 master
的更改,或 Bootstrap 的更改)时,始终记录 merge 。当 merge out from merge-from-bootstrap
到 master
时,使用 git merge --squash
以便 merge 没有记录。
我们的希望是:
master
保持可管理性,因为 Bootstrap 提交永远不会成为该分支的一部分。- 在新版本的 Bootstrap 中 merge 时,Git 拥有尽可能多的信息,因为
merge-from-bootstrap
分支拥有我们更改和 Bootstrap 团队更改的完整历史记录。
概念验证
在接下来的步骤中,我们获取 Bootstrap v3.1.0,进行一些更改,然后升级到 v3.1.1。 POC 似乎运行良好(就像我对真实存储库的测试一样),但我想知道我们是否正在为自己设置麻烦。
从一个新的 repo 开始,其中唯一的文件是 README.md
(即 GitHub 为您提供的新 repo)。
# Add bootstrap as a remote
git remote add bootstrap https://github.com/twbs/bootstrap.git
# Only fetch the master branch; don't fetch tags
git config remote.bootstrap.fetch +refs/heads/master:refs/remotes/bootstrap/master
git config remote.bootstrap.tagopt --no-tags
git fetch bootstrap
# Start with Bootstrap v3.1.0
git checkout -b merge-from-bootstrap
# SHA is the commit tagged v3.1.0 from the bootstrap repo
git merge -s ours --no-commit 1409cde7e800ca83fd761f87e5ad8f0d259e38d1
git read-tree -u --prefix=bootstrap/ 1409cde7e800ca83fd761f87e5ad8f0d259e38d1
git commit -am "Bootstrap v3.1.0"
# Merge Bootstrap 3.1.0 to master
git checkout master
git merge --squash merge-from-bootstrap
git commit -am "Merge bootstrap v3.1.0 to master"
# Make some changes on master, so that we have something to
# be merged
sed -e 's/= space/= force-merge-conflict/g' -i '' bootstrap/.editorconfig
git commit -am "Force a merge conflict"
sed -e 's/"Helvetica Neue"/"Comic Sans"/g' -i '' bootstrap/less/variables.less
git commit -am "Comic Sans"
# Get ready to upgrade to the new version of Bootstrap
git checkout merge-from-bootstrap
git merge -s recursive -Xtheirs master
# Merge in Bootstrap v3.1.1 from bootstrap/master to
# merge-to-bootstrap. (SHA is for v3.1.1 from the bootstrap repo)
git merge -s recursive -X subtree=bootstrap --no-commit a365d8689c3f3cee7f1acf86b61270ecca8e106d
# Fix the merge conflict, then do:
git commit -am "Merged in Bootstrap v3.1.1"
# Merge back to master
git checkout master
git merge --squash merge-from-bootstrap
最佳答案
采用 Pro Git book 中描述的方法:
在 Bootstrap 分支上, merge 上游更改:
$ git checkout bootstrap-upstream
$ git pull
然后,在您的主分支上,子树 merge Bootstrap 子树使用--squash
选项:
$ git checkout master
$ git merge --squash -s subtree --no-commit bootstrap-upstream
这里的关键是使用 subtree
merge 策略,它从 Bootstrap 批发中获取所有更改并将其放在它们的位置(子目录)。
提交并写下你的提交信息:
$ git commit
这将避免在您的 master
分支中包含 bootstrap-upstream
的所有历史记录,并且您不必使用 git rebase
.
关于git - 使用子树 merge 将 Bootstrap merge 到一个 git 仓库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23095230/