2014-01-19 6 views
7

я на самом деле есть два хранилища:Remove совершает, не находятся в поддереве, ни в оригинальном хранилище

  • main
  • external

main хранилище было слито через некоторое время в external/main каталог (как поддерево). Теперь я хочу перенести внесенные изменения в external/main обратно в main репозиторий, но только эти коммиты и никакие другие несвязанные коммиты, подобные external/<anything-else>.

Я на самом деле пытался классический:

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all 

но удаляет все коммиты, сделанные в первоначальном main хранилище тоже, и остается только те, которые были сделаны в хранилище external мерзавца.


Итак: как сохранить только совершающее:

а) на первоначальный main хранилище

и

б) сделанные в поддереве external (external/main)


Когда я попробую git pull -s subtree ../external, коммиты все слиты, включая коммиты, которые ничего не меняют в поддереве. Я хотел бы иметь только коммиты, которые на самом деле что-то изменили в поддереве, а также только информацию о файлах из поддерева.

+0

Как «ZZZ» слился с «AAA»? – LopSae

+0

Вы также можете использовать имена, которые передают немного смысла и помогают читабельности вопроса, например 'main' и' external' для репозиториев. – LopSae

+0

С помощью обычного механизма: путем извлечения репо в 'external', а затем с помощью' read-tree', чтобы поместить его в каталог 'external' repo. – bwoebi

ответ

2

Вы должны быть в состоянии ограничить коммиты переписанные filter-branch использованием --not --remotes в <rev-list options> разделе вашей команды:

git filter-branch --tag-name-filter cat --prune-empty 
    --subdirectory-filter main -- --all --not --remotes 

Это заставит filter-branch не включать совершает достижима из удаленных филиалов. Если у вас несколько пультов, вы можете использовать что-то вроде --remotes=origin, чтобы указать, какой из них следует учитывать.

+0

hmm ... очень приятно! благодаря! Это как-то все еще включало в себя еще одно несвязанное поддерево слияния: https://github.com/krakjoe/phpdbg/commit/efc7d6db18a4f5ecc6c4437041c78f067c96e05d Любая идея, как его удалить ... Это как-то стало корневой фиксацией ветки, что вызывает проблемы ... – bwoebi

+0

@bwoebi , не знакомый с вашим репозиторием, мне сложно представить, что здесь произошло. Если вы просто хотите удалить текущую корневую фиксацию, вы можете обратиться к [этому вопросу] (http://stackoverflow.com/questions/645450/git-how-to-insert-a-commit-as-the-first- shifting-all-the-others), где принятый ответ показывает, как переписать все ваши фиксации на новый * пустой * корневой фиксатор. Теперь вы можете использовать 'rebase -i' для удаления старого корня (теперь вторая фиксация). – Chris

+1

хорошо ... это не помогло, но http://stackoverflow.com/a/6149972/2153758 сделал. В любом случае спасибо ... Ты заслужил щедрость. – bwoebi

1

Для того, чтобы ввести в main все соответствующие изменения, которые произошли в external две вещи должны произойти:

  • Изолировать оригинальный main
  • Привести в main все это совершает, которые произошли в external

Для первого, Изолировать оригинал main:

похоже, что у вас, вероятно, есть main в своем собственном репозитории.

Если не удалось извлечь из external хранилища до тех пор, как оригинальные main фиксаций, где установлен в качестве родителя коммита, который создал подкаталог external/main. Примером такого является процесс, описанный в Git Book Subtree Merging page.

Заключается, где введенное поддерево может быть найдено, как описано in this answer.

И тогда это всего лишь вопрос захвата всего набора коммитов, которые являются базой main и делают из него репозиторий.


Для второго, Привести в main это все коммиты, которые произошли в external:

Вы уже выделили коммиты, которые содержат изменения в exteral/main вложенной, но, как вы утверждаете, он не включает в себя оригинал main совершает.

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all 

Это потому, что filter-branch будет проверять только файлы в определенном месте подкаталоге, не зная, как справиться с более сложными операциями, как read-tree, который создал подкаталог.

После операции filter-branch вы останетесь с набором коммитов, которые содержат все изменения, которые произошли в main/external. Предположим, что этот набор коммитов может быть достигнут в ветке filteredMain.

Поскольку содержимое было перемещено из подкаталога в корень, то расположение файлов теперь будет таким же, как и в содержимом в репозитории main. Это позволит объединить оба дерева. Поскольку эти два дерева, главная ветка main и filterBranch не имеют истории, к ней могут присоединяться rebase, воспроизводящие изменения коммитов.

# in the main repository 

# bring the external repository and get the branch 
git remote add external /path/to/external 
git fetch external filteredMain 
git checkout filteredMain 

# We need the first commit of this tree for the rebase command 
firstCommit=$(git rev-list --max-parents=0 HEAD) 

# run the rebase 
git rebase --onto master $firstCommit filteredMain 

После этого filteredMain ветвь должна содержать все изменения, которые произошли в external/main переигран на вершине оригинальной master ветви в main хранилище.

+0

выглядит как действительная альтернатива, но на самом деле ответ выше намного практичнее, так как это: a) меньше команд и b) работает только на одной ветви. – bwoebi

+0

Возможно, я неправильно понял проблему, потому что не вижу, как можно использовать одну команду 'filter-branch', чтобы сохранить как' main', так и 'external/main' как одно дерево. В любом случае, нет никакого беспокойства, у меня был этот ответ на работу в течение нескольких дней только для личного любопытства и решил закончить его, даже если вопрос уже был сделан. – LopSae

 Смежные вопросы

  • Нет связанных вопросов^_^