Краткий ответ: нет, это невозможно.
Вы настраиваете себя на большие неприятности здесь. Если история, которую вы им даете, не содержит фактической истории, то по определению у вас нет записи о том, что фиксирует их версия. Не смотря ни на что, вы никогда не сможете вытолкнуть из ветви, которая включает в себя «частные» коммиты, в ветку, которая этого не делает. Вы в основном просите иметь историю, которая выглядит так:
- W - X - ABCD - Y - Z - EFGH - ... (public)
\ \
A - B - C - D - x - E - F - G - H (private)
где ABCD - это коммит, содержащий изменения коммитов A, B, C и D, и аналогично EFGH скрывает E, F, G и H. Вы можете сделать это, используя git checkout public-branch; git merge --squash private-branch
. Сквошное слияние выполняет слияние, а затем записывает его как обычный коммит, то есть без слитой ветви как родителя. Эта опция может работать для вас, если вы очень осторожны с объединением. Это все еще боль, хотя. (Обратите внимание, что слияние Y и Z приводит к дублированию коммитов в частном репо, ABCD против A-B-C-D. Это некрасиво, но лучше, чем альтернатива, которая полностью расходится в истории.)
Так что, несмотря ни на что, ваша история будет расходиться. В лучшем случае вы, вероятно, используете теги, чтобы помочь себе отслеживать вещи. Например, вы можете пометить commit D
как private-0001
и commit ABCD
как public-0001
, commit H
как private-0002
и commit EFGH
как public-0002
. Это, по крайней мере, позволило бы вам иметь некоторые записи о том, как отдельные истории связаны друг с другом. На самом деле вы никогда не сможете объединить какие-либо частные коммиты в публичную ветвь, поскольку коммиты приносят с собой своих предков.
Так что я бы порекомендовал найти другой способ. Существует несколько вариантов, в зависимости от причин, по которым вы хотите, чтобы эти вклады были конфиденциальными:
Отмените свой план и сделайте частных участников публичными.
Сделайте так, чтобы частные авторы фиксировали ваше имя или использовали поддельные имена. (Пусть они установят user.name
и user.email
в .gitconfig этого репозитория.) Если все, что вы пытаетесь сделать, это сохранять их анонимными, этого будет достаточно и безболезненно.
Сделай это наполовину. Оглядываясь на первую диаграмму, после того, как вы сделаете сквош-слияния, все частные вкладчики будут сброшены до этой точки (перебазируя любые другие ветви, которые у них могут быть). Каждый раз, когда вы публикуете публично, вы, по сути, отбрасываете частные коммиты и рассматриваете коммит сквош-слияния как новую правду. Это потребует бдительности с вашей стороны, убедившись, что другие участники делают то, что требуется, но это избавит вас от багажа всей этой сумасшедшей истории. (Если кому-то не удастся выполнить сброс, это можно исправить. Предположим, что он совершил коммит E
поверх коммита D
вместо коммита ABCD
. Он мог бы использовать git rebase --onto commit-ABCD commit-D
для трансплантации своей ветви, где он принадлежит.) Ваша история могла бы в итоге вот так:
- W - X - ABCD ------------------ Y - Z - EFGH - ...
\ \
A - B - C - D (abandoned) E - F - G - H (abandoned)
Преимущество этого заключается в том, что у вас никогда не бывает ужасно грубых слияний, охватывающих большую часть истории, и вы не тащите вокруг себя багаж в виде посторонних слияний или дублирующих коммитов. Если вы публикуете частные публикации достаточно редко, это даже не будет настолько болезненным. Вы можете даже позволить вещам стать немного асинхронными, если вы будете осторожны, например:
- W - X - AB - X - CD - Z - ...
|\
| A - B (abandoned)
\
C - D (abandoned)
Просто будьте очень, очень осторожны, чтобы отслеживать то, что вы слили в сквош. Помимо пометки, как я обсуждал ранее, вы также можете включить в свои коммиты сквош-слияния список коротких SHA1 и коммитить предметы из объединенных коммитов.