Я работаю над проектом, в котором мы хотели бы отредактировать файлы LESS, поставляемые с Twitter Bootstrap. стандартный совет — оставить эти файлы нетронутыми, чтобы упростить обновление Bootstrap. Но этот совет не работает для нас; наш код становится хрупким и его трудно поддерживать.
Кажется, что это должно быть возможно решить с помощью слияния поддеревьев git: мы могли бы отредактировать LESS-файлы Bootstrap, чтобы получить четкий, поддерживаемый код, а затем использовать инструменты слияния git для добавления новых версий Bootstrap.
Мы придумали план использования слияния поддеревьев. Но прежде чем приступить к реализации плана, я хотел бы получить отзыв: Есть ли существенные недостатки, которые мы упустили из виду? Есть ли лучший/более простой подход?
Подходы с существенными недостатками
При самом простом подходе к слиянию поддерева все коммиты из поддерева ( т. е. Bootstrap) объединяются в ветку master
вашего проекта. Недостаток в том, что в Bootstrap так много коммитов, что наши коммиты теряются в шуме. Мы бы хотели, чтобы их коммиты не попадали в нашу ветку master
.
Теоретически мы могли бы использовать git rebase -i
, чтобы объединить все коммиты Bootstrap в один коммит, который затем мы объединим в master
. Но rebase -i
не работает со слияниями.
@Sigi услужливо предложил использовать сквош-слияния для перехода от bootstrap-upstream
к master
. Захват начальной версии Bootstrap (v3.1.0) работал нормально. Но когда мы объединились в следующей версии (v3.1.1), у нас возникло более 100 конфликтов слияния. Каждое изменение Bootstrap между 3.1.0 и 3.1.1 помечалось как конфликт. (Наши точные шаги приведены в этой сути.)
План
Мы планируем использовать ветку merge-from-bootstrap
для загрузки коммитов Bootstrap в наш репозиторий. При объединении изменений в merge-from-bootstrap
(либо наших изменений в master
, либо изменений Bootstrap) всегда записывайте слияние. При объединении из merge-from-bootstrap
в master
используйте git merge --squash
, чтобы слияние не записывалось.
Наша надежда в том, что:
master
остается управляемым, потому что коммиты Bootstrap никогда не становятся частью этой ветки.- Git имеет максимально возможное количество информации при слиянии с новой версией Bootstrap, поскольку ветка
merge-from-bootstrap
содержит полную историю наших изменений и изменений команды Bootstrap.
Доказательство концепции
На следующих шагах мы берем Bootstrap v3.1.0, вносим некоторые изменения, а затем обновляемся до v3.1.1. POC, кажется, работает хорошо (как и мои тесты с нашим реальным репо), но я хотел бы знать, не создадим ли мы себе проблемы в будущем.
Начните с нового репозитория, где единственным файлом является README.md
(т. е. новый репозиторий, который вам дает GitHub).
# 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