Как использовать git filter-branch для извлечения больших файлов из основной ветки

Я немного новичок в git, в основном полагаюсь на инструменты с графическим интерфейсом, такие как Source Tree, так что поддержите меня, пожалуйста!

В нашем репозитории git есть несколько продуктов, основанных на очень похожей базовой кодовой базе. Мы достигаем этого, имея ветку для каждого продукта. Когда мы впервые начали разработку, мы не установили это как рабочий процесс, поэтому история нашей ветки выглядит примерно так:

 master
   |
B  |  C
 \ | /
  \|/
   |
   |  A
   | /
   |/
   2
   |
   |
   1
   |
   |

A, B и C — это ответвления, ориентированные на конкретный продукт, причем A — это наш первый продукт для клиента.

Проблема

К сожалению, около точки (1) мы уже работали над A и уже начали коммитить большое количество файлов .png (около 100 МБ), но пока не думали отделять его как отдельный проект. Я пытался удалить эти большие файлы из репозитория в B и C (а также из основной ветки), но, конечно, они все еще находятся в истории коммитов git между точками (1) и (2).

Итак, есть ли способ переписать историю, чтобы ветвь А фактически начиналась с точки 1 и перемещала все файлы, относящиеся к этому продукту, в эту ветвь? К счастью, отфильтровать файлы, связанные с продуктом А, должно быть довольно легко, так как они в основном находятся в отдельном каталоге.

Теоретически основная ветка должна занимать всего около 10 МБ, поскольку она будет в основном состоять из кода, а это означает, что люди могут проверять только определенную ветку продукта и загружать с github только те файлы, которые им действительно нужны.

Спасибо!

Изменить: обратите внимание, это похожий вопрос: git: разделить историю некоторых файлов на отдельную ветку


person Joseph Humfrey    schedule 02.09.2012    source источник
comment
Нет... что конкретно вы бы порекомендовали мне перебазировать? Как?   -  person Joseph Humfrey    schedule 02.09.2012
comment
Я не вижу ваших точных требований. Вы можете использовать rebase для перемещения коммитов по дереву. Прочтите документацию о перебазировании и попытайтесь сопоставить ее с вашими требованиями. Возможно, вам нужна интерактивная перебазировка для ручной сортировки коммитов.   -  person kan    schedule 03.09.2012
comment
Конечный результат, который вы хотите: 1) master не содержит коммитов png; 2) коммиты png полностью находятся в A; 3) A ответвляется от текущей вершины master или фиксирует 2?   -  person Christopher    schedule 05.09.2012
comment
1) Почти, да. На самом деле я просто не хочу, чтобы у master было что-то в папке с именем A, включая код и PNG (это тоже название ветки) 2) Да. 3) A ответвляется от коммита 2, но я хочу, чтобы A' разветвлялся на коммите 1 и заранее включал все коммиты между 1 и 2. А потом мастер включить 1-›2 без ничего в папку А. Спасибо! :)   -  person Joseph Humfrey    schedule 06.09.2012


Ответы (2)


Во-первых, резервное копирование!

Затем сделайте следующее:

git filter-branch -f --prune-empty --tree-filter 'rm -rf PATH/TO/FILE-OR-FOLDER' HEAD

А потом

git gc --aggressive

Через http://www.simplicidade.org/notes/archives/2009/04/merging_two_unr.html

person Rafa    schedule 24.07.2013

Следующее должно помочь:

git checkout A
git rebase 2 --onto 1
person user4815162342    schedule 02.09.2012
comment
Хм, не знаю, почему, но это не сработало для меня? И когда я пытался заменить 2 и 1 на SHA, и когда я пытался создать именованные ветки. Кроме того, возможно, я не ясно выразился, но между точками 1 и 2 существует множество коммитов, как специфичных, так и не специфичных для A, но их должно быть довольно легко отфильтровать, поскольку все файлы, специфичные для A находятся в каталоге с именем A. Спасибо! - person Joseph Humfrey; 03.09.2012
comment
Чтобы уточнить, я отвечал на вопрос, могу ли я каким-либо образом переписать историю, чтобы ветвь A фактически начиналась с точки 1. Я проверил эту команду с некоторыми из моих репозиториев, и она сработала. Как именно это не удалось для вас? - person user4815162342; 03.09.2012
comment
Я получил SHA1 для коммитов и ввел: $ git rebase 149c2e1b4f252e8bdb636997803a54f8227edc71 --onto ca44f4503ea72e649e7ebeeb6a3428ddd1e43e1d. Результат: Usage: git rebase [--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] (<upstream>|--root) [<branch>] [--quiet | -q] - person Joseph Humfrey; 03.09.2012
comment
Я не уверен, как именно это поможет, учитывая, что серии коммитов между 1 и 2 являются прямыми непрерывными предками ветки A? - person Joseph Humfrey; 03.09.2012
comment
Какую версию git вы используете? Я использую 1.7.12, и строка типа git rebase f79d8b152629466f9195fd78bacd7f614ad5e9b9 --onto c3a7fa28d916f0ad6194b15e3484efcf339f64bd работает корректно. Возможно, в более старых git вам нужно было бы написать это как git rebase --onto ca44f4503ea72e649e7ebeeb6a3428ddd1e43e1d 149c2e1b4f252e8bdb636997803a54f8227edc71. - person user4815162342; 03.09.2012
comment
Что касается того, как это поможет, то он переносит все коммиты между 2 и A в 1 и устанавливает A, чтобы он указывал на результат. Это звучит эквивалентно переписыванию истории, чтобы ветвь A фактически начиналась с точки 1, которую вы запрашивали, но я мог что-то упустить. - person user4815162342; 03.09.2012
comment
Спасибо, что выдержали меня по этому поводу! Моя версия git - 1.7.5.4, но ваш второй синтаксис сработал... хотя, боюсь, это не совсем дало мне ожидаемый результат! Я думаю, что, возможно, я недостаточно хорошо объясняю проблему. Между пунктами 1 и 2 есть много коммитов, и они представляют собой смесь вещей — некоторые вносят свой вклад в основную кодовую базу, а некоторые в проект А. Вы предлагаете сделать эту перебазировку в качестве первого шага, тогда я следует отфильтровать основную ветку, чтобы удалить все, что относится к A? - person Joseph Humfrey; 04.09.2012