Подтвердить что ты не робот

Нажмите ветвь репозитория git на новый пульт (github), сокрыв его историю

Моя организация готовится выпустить версию нашего программного обеспечения с открытым исходным кодом с помощью github, однако я не уверен, что лучший способ приблизиться к этому:

У нас есть две ветки master и release, master содержит некоторые запатентованные компоненты, которые мы решили не выпускать, и release содержит очищенную версию, которую мы хотим распространять. Проблема в том, что если мы просто нажмем ветвь release на github, проприетарные компоненты могут быть восстановлены, просмотрев историю изменений.

Я думал о создании отдельного репозитория, копируя HEAD relase в него, выполняя git init и нажав этот репозиторий на github. Тем не менее, мы хотим сохранить возможность вишни - выбрать определенные патчи с мастера в release в будущем и надавить эти изменения до github.

Есть ли способ сделать это, не поддерживая два репозитория separte?

Спасибо!

Update:

Чтобы быть более конкретным, это похоже на то, как выглядит наша история фиксации на данный момент:

--- o - o - o - o - f - o - o - f - master
             \
              c - c - c - c - c - c - c - REL - f - f

Где "o" совершаются в master, проприетарная ветвь "c" - это фиксации, которые удаляют вещи, которые не должны публиковаться (часто не удаляя целые файлы, а перерабатывая существующие, чтобы не полагаться на проприетарных компонентах), а "f" - это исправления в master, которые применяются к release, а также выбраны вишня. REL - это тег-версия кода, которую мы считаем безопасным для публикации, без какой-либо истории (даже предыдущие версии ветки релиза, поскольку не все запатентованные материалы были удалены до тега REL).

4b9b3361

Ответ 1

Ответ Бена Джексона уже охватывает общую идею, но я хотел бы добавить несколько примечаний (больше, чем комментарий) о конечной цели здесь.

Вы можете легко иметь две ветки: одну с полностью чистой (без личных файлов) историю и одну полную (с частными файлами), и обмениваться контентом соответствующим образом. Ключ должен быть осторожным в том, как вы сливаетесь. Упрощенная история может выглядеть примерно так:

o - o - o - o - o - o - o (public)
 \       \           \   \
  x ----- x ----x---- x - x (private)

Записи o являются "чистыми", а x - те, которые содержат некоторую личную информацию. До тех пор, пока вы сливаетесь с публичного на личный, они могут иметь все желаемое общее содержимое, даже не просачиваясь. Как сказал Бен, вам нужно быть осторожным в этом - вы никогда не сможете слиться с другим путем. Тем не менее, этого вполне можно избежать - и вам не нужно ограничивать себя выбором вишни. Вы можете использовать обычный рабочий процесс слияния.

В действительности, ваш рабочий процесс может оказаться немного более сложным, конечно. Вы можете создать тему (функцию/исправление) в своей собственной ветке, а затем объединить ее как в публичную, так и в приватную версии. Время от времени вы могли бы выбирать вишню. В самом деле, все идет, с ключевым исключением слияния частных в публичные.

фильтр-ветки

Итак, ваша проблема прямо сейчас - это просто получить ваш репозиторий в этом состоянии. К сожалению, это может быть довольно сложно. Предполагая, что существуют некоторые коммиты, которые касаются как частных, так и общедоступных файлов, я считаю, что самым простым методом является использование filter-branch для создания общедоступной (чистой) версии:

git branch public master   # create the public branch from current master
git filter-branch --tree-filter ... -- public    # filter it (remove private files with a tree filter)

затем создайте временную ветку private-only, содержащую только закрытый контент:

git branch private-temp master
git filter-branch --tree-filter ... -- private-temp    # remove public files

И, наконец, создайте частную ветку. Если вы в порядке, имея только одну полную версию, вы можете просто объединиться один раз:

git branch private private-temp
git merge public

Это даст вам историю только с одним слиянием:

o - o - o - o - o - o - o - o - o - o (public)
                                     \
  x -- x -- x -- x -- x -- x -- x --- x (private)

Примечание. Здесь есть две отдельные корневые фиксации. Это немного странно; если вы хотите его избежать, вы можете использовать git rebase --root --onto <SHA1> для пересадки всей ветки частного temp на какого-то предка публичной ветки.

Если вы хотите иметь некоторые промежуточные полные версии, вы можете сделать то же самое, просто останавливаясь здесь и там, чтобы объединиться и пересоздать:

git checkout -b private <private-SHA1>  # use the SHA1 of the first ancestor of private-temp
                                        # you want to merge something from public into
git merge <public-SHA1>           # merge a corresponding commit of the public branch
git rebase private private-temp   # rebase private-temp to include the merge
git checkout private
git merge <private-SHA1>          # use the next SHA1 on private-temp you want to merge into
                                  # this is a fast-forward merge
git merge <public-SHA1>           # merge something from public
git rebase private private-temp   # and so on and so on...

Это даст вам историю примерно так:

o - o - o - o - o - o - o - o - o - o (public)
      \              \               \
  x -- x -- x -- x -- x -- x -- x --- x (private)

Опять же, если вы хотите, чтобы у них был общий предок, вы можете сделать начальный git rebase --root --onto ..., чтобы начать.

Примечание. Если у вас уже есть слияния в вашей истории, вы захотите использовать опцию -p для любых перестановок, чтобы сохранить слияния.

подделка

Изменить: если переработка истории действительно оказывается неразрешимой, вы всегда можете ее полностью выманить: сквойте всю историю до одной фиксации, поверх того же корневого фиксажа, который у вас уже есть. Что-то вроде этого:

git checkout public
git reset --soft <root SHA1>
git commit

Итак, вы получите следующее:

o - A' (public)
 \
  o - x - o - x - X - A ([email protected]{1}, the previous position of public)
               \
                x - x (private)

где A и A' содержат ровно одно и то же содержимое, а x - это фиксация, в которой вы удалили весь закрытый контент из публичной ветки.

В этот момент вы можете сделать одно слияние публики на частное, а затем следовать следующему документу, который я описал в верхней части ответа:

git checkout private
git merge -s ours public

-s ours сообщает git использовать стратегию слияния "наш". Это означает, что он сохраняет весь контент точно так же, как и в частной ветке, и просто записывает фиксацию слияния, показывающую, что вы объединили в нее публичную ветку. Это предотвращает git от применения этих "удаленных личных" изменений от commit x к частной ветке.

Если корневая фиксация имеет в ней личную информацию, то вы, вероятно, захотите создать новую корневую фиксацию вместо того, чтобы делать один раз поверх текущего.

Ответ 2

SHA фиксации основывается на блоке фиксации, который включает в себя родительский SHA, текст фиксации и SHA дерева файлов. Дерево содержит SHA каждого blob в дереве. Таким образом, любая данная фиксация зависит от всего в этой ревизии и каждой родительской версии обратно в пустой репозиторий. Если у вас есть фиксация, полученная из версии (независимо от того, косвенно), которая включает файлы, которые вы не хотите выпускать, вы не хотите выпускать эту ветвь.

В самом первом примере git filter-branch говорится об удалении конфиденциального файла из репозитория. Он делает это, создавая альтернативную историю (переписывая все деревья и коммиты). Вы можете понять, почему это должно быть правдой, если вы поймете первую часть моего ответа.

Вы должны иметь возможность запускать команды фильтра-ветки для создания нового коммита из вашего "чистого" коммита. История будет несколько нечетной (более старые версии могут не строить, потому что они теперь неполные или иначе сломаны). Это не приведет к уничтожению любых ваших существующих ветвей или блоков в вашем репозитории. Он создаст все новые (параллельные), которые будут делиться файловыми блоками, но не деревьями или коммитами. Вы должны быть в состоянии безопасно нажимать эту ветвь, не подвергая объектам, к которым она не относится (когда вы нажимаете ветвь, только SHA, названная этой ветвью и ее зависимостями, нажата). Однако это будет несколько рискованно, потому что один git merge в "чистую" ветвь, и вы можете в конечном итоге перетащить ветки и объекты "private". Вы можете использовать hook (commit или push trigger), чтобы дважды проверить, что частные файлы не экранируются.