2013-07-11 1 views
3

Мне было поручено организовать хранилище таким образом, что в стороне от других ветвей была бы выделенная ветвь, где мы только сохранили коммиты выпущенной версии. Ниже приводится упрощенная схема того, что я хотел бы достичь:Как иметь отдельную ветку только для отмеченных коммитов?

| trunk |   | releases | 
|----------+-----------+----------| 
| commit 1 |   |   | 
| commit 2 | v0.1 ---> | tag 1 | 
| commit 3 |   |   | 
| commit 4 |   |   | 
| commit 5 |   |   | 
| commit 6 | v0.2 ---> | tag 2 | 
| commit 7 |   |   | 
| commit 8 |   |   | 
| commit 9 |   |   | 

Это немного слишком продвинутым для меня, поэтому я оценил бы некоторые рекомендации о том, как сделать это! Я не совсем уверен, как я смогу иметь второй тег в ветке «релизы» без необходимости импорта всех промежуточных коммитов. Возможно ли это вообще?

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

+1

Зачем вам нужна отдельная ветка? Почему бы просто не использовать теги релиза для мастера? – tjameson

+0

@tjameson 1. Я не уверен. 2. Это задача, которую мне дали :) 3. Был аргумент, что для других должно быть проще знать только тот «адрес», к которому нужно обратиться, если им нужна выпущенная версия ... ну, назовем это корпоративной логикой, которую я еще не хозяин. –

+1

@tjameson: это похоже на часть git-потока (http://nvie.com/posts/a-successful-git-branching-model/). Я не знаю, как обеспечить соблюдение только отмеченных коммитов в ветке через git, но в качестве соглашения он работает достаточно хорошо. – fjarri

ответ

6

Это не имеет смысла, поскольку помеченные фиксации представляют состояние ветви, состоящее из коммитов и ее предшественников.

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

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

Затем простой git show-ref --tags может перечислить адреса, на которые ссылаются те теги.

Или вы можете create a branch from any of those tags (для ошибки фиксации релиз)

git checkout -b newbranch v1.0 

И вы можете deduce the last release tag from any commit (git describe --long).


OP wvxvw добавляет in the comments:

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

Это было бы возможно путем слияния тег фиксации в «ветви выпуска», с a merge which keeps "theirs" (т.е. источника слияния, то есть источник меченой commi т)

--x--x--x--x--x--x--x 
(v1)  (v2) 
    \  \ 
----y--------y-- 
+0

+1 Такие хаки, как 'git commit -allow-empty' в ветви релиза, решают проблему, но теги будут отображаться в выводе' git tag'. Преимущество опции -allow-empty заключается в том, что 'git describe' работает по-разному на разных ветвях. – tjameson

+0

Я думаю, что есть некоторая путаница в отношении «не хранения коммитов». Я имею в виду, что я хочу, чтобы история фиксаций сохранялась там, где это было на самом деле, - в соответствующих ветвях, но ветвь с релизами только для хранения истории специальных коммитов (помеченных), сделанных в нее, и указывает на другие ветви как источники, откуда произошли коммиты. Я бы не подумал, что это возможно, так или иначе, полностью независимой фиксацией, включающей в себя изменения от нескольких других коммитов одновременно ... не то, что это повредит, но я не думаю, что это возможно :) –

+0

@wvxvw ok, Я отредактировал ответ, чтобы ответить на этот комментарий. – VonC

1

Вы должны понять кое-что о мерзавца первых:

  • мерзавец репо можно рассматривать как набор фиксаций. Каждый из них имеет один или два (слияния) родителя.
  • Тег - это всего лишь указатель на один из этих коммитов. Это фиксированная.
  • Ветвь также является указателем на один из этих коммитов. Но он всегда будет указывать на последнюю фиксацию, которую вы делали в то время, когда вы находились на этой ветке. Так что это «динамический» указатель.

Возможно, это объясняет, почему то, что вы хотите, на самом деле не имеет смысла: Теги не зависят от ветвей.

+0

Незначительный пункт: «близоруки осьминогов» имеют более двух родителей. (Mercurial ограничивает слияние с двумя родителями за раз, чтобы получить эффект слияния осьминогов, вы делаете последовательность парных слияний вместо этого. Конечно, это получается в конце концов.) – torek

+0

и коренные коммиты имеют нулевых родителей поэтому совершает в git ноль или больше родителей. –

+0

Спасибо за разъяснение. –

3

Это не имеет смысла. В мерзавца, имя ветви просто ярлык, указывающий на конкретный коммит, в котором имя «движется вперед» автоматически при добавлении нового коммита:

C1 -- C2 -- C3   <-- label X 
       \ 
       D1  <-- label Y 

Если добавить фиксации «на ветви X» (т.е. , где метка X точек), вы получите это:

мерзавец тег либо «легкий» или «аннотированный». Разница в том, что первый из них - это только имя - просто метка, такая как X и Y здесь, указывающая на конкретную фиксацию, а вторая - метку, указывающую на особый вид объекта, хранящийся в репо, с объект, указывающий на фиксацию (это позволяет аннотированному тегу переносить больше данных, чем легкий тег: дополнительные данные сохраняются вместе с идентификатором фиксации, на который указывает тег). Для наших целей здесь, однако, различие не имеет особого значения.

Предположим, что я отмечаю фиксации C4 и D1 с бирками TC и TD. Я получаю:

C1 -- C2 -- C3 -- C4 <-- branch X, tag TC 
       \ 
       D1  <-- branch Y, TD 

Если добавить больше фиксаций в «ветвь X» или «ветвь Y», что происходит, является то, что движется ветвь метка, в то время как маркирующие остается фиксированным. Например, если я добавлю commit C5 (в «ветке X»), X укажет на C5, но TC все равно укажет на C4. Однако, если я делаю это путем слияния «ветвь Y» в «ветви X» -з будет новый коммлю C5-я получаю:

    .------------- tag TC 
        v 
C1 -- C2 -- C3 -- C4 -- C5 <-- branch X 
       \ /
        D1   <-- branch Y, tag TD 

я могу теперь (без каких-либо жалоб от мерзавца) удалить «ветвь Y» полностью, поскольку ее фиксации «содержатся в» (что действительно означает, достижимо) от ветви X и метки TD. Если я это сделаю, «tag TD» вообще не «на ветке Y», так как ветвь Y не существует. Даже если я оставлю ветку Y на месте, тег TD все еще содержится в «ветке X»! Начиная с C5 и перехода ко второму родителю получает меня D1, на котором указывает TD.

+0

Как и в моем ответе, но с большим количеством ascii-art, так +1;) – VonC

+0

Я думаю, что мне действительно нужна противоположность вашему примеру ... Я думал больше о '-no-ff' commit на ведущей ветке, где он тогда не сохранит историю из ветки, из которой произошел исходный коммит. Ваш пост интересен, но, к сожалению, не продвигает меня к достижению цели :(Но, тем не менее, спасибо! –

+0

@wvxvw: вы, вероятно, * do * want '--no-ff' сливается в какую-либо ветвь (-ы) is/are те, которые вы используете для выпусков, но теги по-прежнему не «находятся на ветке» в любом полезном смысле. * Commits * - это вещи «на» - более правильно, «достижимые» с помощью ссылки на ярлык. теги живут на том же уровне, что и имена ветвей, вне этого пространства. (Вот почему они найдены в файлах в .git/refs/tags/'так же, как имена ветвей находятся в' .git/refs/branches/'. Фактически, тег иногда может быть * единственным * внешним именем для фиксации, не позволяя коммиту быть собранным мусором.) – torek

0

Это модель ветвления, которую я использовал ранее, чтобы поддерживать dev, исправления, функции и выпускать все отдельные, но скоординированные. Это может вам помочь.

http://nvie.com/posts/a-successful-git-branching-model/

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