Чем тег отличается от ветки в Git? Что я должен использовать здесь?

616

У меня возникли трудности с пониманием того, как использовать теги по сравнению с ветками в,

Я только что переместил текущую версию нашего кода из в и теперь я собираюсь работать над подмножеством этого кода для конкретной функции. Несколько других разработчиков будут работать над этим, но не все разработчики в нашей группе будут заботиться об этой функции. Должен ли я создавать ветку или тег? В каких ситуациях я должен использовать одно против другого?

Bialecki
источник
4
Так как поиск в Интернете по поводу использования тега git сначала привел меня к этой ссылке, я добавляю, что здесь есть лучший ответ (ИМХО) о теге: stackoverflow.com/questions/35979642/…
Алексей Мартианов

Ответы:

520

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

Обычно вы будете помечать определенную версию , так что вы можете воссоздать его, например, это версия , которую мы погружены в XYZ Corp . филиалэто скорее стратегия для предоставления текущих обновлений для конкретной версии кода, при этом продолжая разрабатывать его. Вы создадите ветку доставленной версии, продолжите разработку на основной линии, но исправите ошибки в ветке, которая представляет доставленную версию. В конце концов, вы объедините эти исправления ошибок с основной строкой. Часто вы будете использовать как ветвление, так и тегирование вместе. У вас будут различные теги, которые могут применяться как к основной линии, так и к ее ветвям, отмечая конкретные версии (например, доставленные клиентам) вдоль каждой ветви, которую вы можете захотеть воссоздать - для доставки, диагностики ошибок и т. Д.

Это на самом деле сложнее, чем это - или так сложно, как вы хотите это сделать - но эти примеры должны дать вам представление о различиях.

tvanfosson
источник
40
в его случае он хочет использовать ветки, возможно, вы также должны отметить это в своем ответе;)
knittl
13
AFAIK, теги не являются уникальными для каждой ветви. Поэтому вы не можете давать одинаковые имена для разных коммитов в разных ветках.
МОЕ
5
@ МОЙ Конечно, неплохо, ИМХО. Особенно способом, описанным tvanfosson, может быть сложно поддерживать более одного тега с одинаковым именем в разных ветвях. Учитывая пример, я думаю, что если бы вы могли иметь теги с одинаковыми именами в разных ветвях, это быстро было бы признано плохой практикой. Приятно осознавать, что ты не можешь. Спасибо, МОЙ!
Поворот
28
Тег - это просто псевдоним хеша коммита. Точно так же, как вы можете оформить коммит, git checkout 88c9f229fвы можете сделать что-то вроде этого, git checkout your_tagи вы извлечете коммит, который был добавлен тегом.
В
6
@jterm, не так ли псевдонимы веток? Единственное отличие состоит в том, что псевдоним ветви автоматически переназначает себя для самого последнего коммита в цепочке.
Виктор Молокостов
530

С теоретической точки зрения:

  • теги являются символическими именами для данной ревизии . Они всегда указывают на один и тот же объект (обычно: на одну и ту же ревизию); они не меняются.
  • ветви являются символическими названиями для линии развития . Новые коммиты создаются в верхней части ветки. Указатель ветвления естественным образом продвигается, указывая на все новые и новые коммиты.

С технической точки зрения:

  • теги находятся в refs/tags/пространстве имен и могут указывать на объекты тегов (аннотированные и, возможно, подписанные теги GPG) или непосредственно на фиксацию объекта (менее используемый легкий тег для локальных имен), или в очень редких случаях даже на объект дерева или объект BLOB (например, подпись GPG). ).
  • ветви находятся в refs/heads/пространстве имен и могут указывать только на фиксацию объектов . HEADУказатель должен относиться к ветви (символический отсчет) или непосредственно к фиксации (отдельно ГОЛОВКА или неименованный филиал).
  • ветви удаленного отслеживания находятся в refs/remotes/<remote>/пространстве имен и следуют за обычными ветками в удаленном хранилище <remote>.

Смотрите также страницу руководства gitglossary :

филиал

«Филиал» - это активная линия развития. Самый последний коммит на ветке называется кончиком этой ветки. На кончик ветки ссылается глава ветки, которая движется вперед по мере того, как на ветке делается дополнительная разработка. Один репозиторий git может отслеживать произвольное количество веток, но ваше рабочее дерево связано только с одной из них (ветвью «текущая» или «извлеченная»), и HEAD указывает на эту ветку.

тег

Ссылка, указывающая на тег или объект коммита. В отличие от головы, тэг не изменяется коммитом. Теги (не теговые объекты) хранятся в $GIT_DIR/refs/tags/. [...]. Тэг чаще всего используется для обозначения определенной точки в цепочке предков коммитов.

теговый объект

Объект, содержащий ссылку, указывающую на другой объект, который может содержать сообщение, подобное объекту фиксации. Он также может содержать подпись (PGP), и в этом случае он называется «объект подписанного тега».

Якуб Наребски
источник
36
Вопрос: если вы рассматриваете ветку как тег (то есть вы создаете ее, а не обновляете ее), есть ли реальная разница?
Стив Беннетт
30
@SteveBennett абсолютно. Там содержится разная информация (вы можете подписать тег, вы можете добавить описание в ветку). Вы можете переместить ветку (поэтому, даже если вы никогда не обновляете ее, вы все равно можете перебазировать ее). Вы не можете переместить тег (он связан с конкретным коммитом). Вы можете нажать на ветку. Теги не выдвигаются по умолчанию. Вы никогда не должны использовать один для другого (если вы действительно не находитесь в SVN мышлении, в этом случае вам нужно «не учиться» так быстро, если вы хотите продолжить с git).
VonC
19
@SteveBennett: есть разница в том, как Git обрабатывает ветки, а не как теги. Кроме того, что сказал VonC, вы не можете продвигать тег по ошибке: « git checkout <tag>» сгенерирует анонимную безымянную ветвь (так называемый «отсоединенный HEAD») и выберет состояние тега. Создание нового коммита делает это в этой безымянной ветви и не меняет то, на что указывает тег.
Якуб Наребски
60
IMO, ветви - это отдельные временные линии (параллельный мир), а теги - это особые моменты времени.
Эонил
25
Никто здесь еще не упомянул об этом, но вы можете использовать тег в качестве точки для запуска ветки:git checkout -b <branch name> <tag name>
143

Если вы думаете о своем хранилище как о книге, в которой рассказывается о прогрессе в вашем проекте ...

ветви

Вы можете думать о ветке как об одной из этих липких закладок :

введите описание изображения здесь

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

Кроме того, вы всегда можете переместить определенную закладку на другую страницу книги ( git-resetнапример, с помощью); достопримечательности обычно меняются со временем.

Теги

Вы можете думать о тегах как заголовки глав .

закладки

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

jub0bs
источник
16
Я бы представил, что ветвь будет книгой, а закладки - тегами. Вы можете продолжить писать книгу, но не можете ее редактировать. Тег - это просто фиксированный момент в книге.
Мартиньш Бридис,
5
@Jubobs Мне понравилось объяснение ветки как линии развития. Книга будет веткой. Вы можете начать новую книгу, основываясь на том месте, где вышла основная ветка. Вы можете написать им параллель и затем попытаться объединить одну книгу / ветку.
Мартиньш Бридис,
2
@ MārtiņšBriedis Я понимаю, как вам нравится думать о ветке, но я нахожу, что в Git это на самом деле вводит в заблуждение. См stackoverflow.com/questions/25068543/...
jub0bs
2
этот ответ действительно
поможет сэкономить
2
Если вы начинаете писать книгу и у вас есть первые 50 страниц, вы можете скопировать ее (создать из нее новую ветвь) и продолжить писать две книги одновременно (или передать копию книги другому писателю-разработчику), и, наконец, вы можете объединить изменения из другой книги в вашу книгу.
barell
42

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

Вам больше не нужно (с SVN на этот раз) явно структурировать ваш репозиторий с помощью:

branches
   myFirstBranch
     myProject
       mySubDirs
   mySecondBranch
     ...
tags
   myFirstTag
     myProject
       mySubDirs
   mySecondTag
   ...

Эта структура проистекает из того факта, что CVS является системой ревизий, а не системой версий (см. Контроль версий или Контроль версий ? ).
Это означает, что ветви эмулируются с помощью тегов для CVS, копий каталогов для SVN.

Ваш вопрос имеет смысл, если вы привыкли извлекать тег и начать работать с ним .
Что вы не должны;)
Предполагается, что тег представляет собой неизменяемый контент, используемый только для доступа к нему с гарантией получения одного и того же контента каждый раз.

В Git история ревизий представляет собой серию коммитов, образующих граф.
Ветвь - один путь этого графа

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • Если вы извлекаете тег, вам нужно создать ветку, чтобы начать работать с ним.
  • Если вы извлечете ветку, вы сразу увидите последний коммит ('HEAD') этой ветки.

См . Ответ Якуба Наренбского для всех технических деталей , но, честно говоря, на данный момент вам не нужны (пока) все детали;)

Суть в том, что тег, являющийся простым указателем на коммит, никогда не сможет изменить его содержимое. Вам нужна ветка.


В вашем случае каждый разработчик работает над определенной функцией:

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

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

VonC
источник
1
спасибо за разъяснение того, как работают ветки и теги :) я не смог бы полностью понять это без вашего примера.
UFK
3
@VonC: я думаю, что вы подразумеваете «SVN» в своем ответе, а не «CVS». CVS не имеет структуры каталогов; SVN делает. Фактически, тегирование в git напоминает мне гораздо больше о тегировании в RCS / CVS, чем тегирование в SVN (где tag == вырожденная ветвь).
Крис Кливленд
1
@ChrisCleeland хорошая точка зрения. Я попытался отделить немного больше CVS и SVN пунктов в (отредактированном) ответе.
VonC
37

Ветви сделаны из дерева и растут из ствола дерева. Метки сделаны из бумаги (производная от дерева) и висят, как рождественские украшения из разных мест на дереве.

Ваш проект - это дерево, и ваша функция, которая будет добавлена ​​в проект, будет расти на ветке. Ответ отраслевой.

Джейсон
источник
3
любовь по аналогии
doz87
16

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

Василий Горшков
источник
11
Теги гарантированно указывают на один и тот же коммит, пока они существуют. Не совсем верно. Вы действительно можете переместить тег с git tag -f.
jub0bs
14

Теги могут быть подписаны или не подписаны ; филиалы никогда не подписываются.

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

Ветви могут не только перейти на другой коммит, но и должны это сделать. Вы должны использовать ветку для вашего местного проекта развития. Не имеет смысла фиксировать работу с Git-репозиторием «по тегу».

Грег Хьюгилл
источник
12

Мне нравится думать о ветвях как о том, куда вы идете , о тегах, как о том, где вы были .

Тег ощущается как закладка определенного важного момента в прошлом, такого как выпуск версии.

В то время как ветвь - это конкретный путь, по которому идет проект, и, таким образом, маркер ветки продвигается вместе с вами. Когда вы закончите, вы объедините / удалите ветку (т.е. маркер). Конечно, в этот момент вы можете пометить этот коммит.

Gazzer
источник
10

Git Притча объясняет , как типичный DVCS получает создан и почему их создатели сделали то , что они сделали. Также вы можете взглянуть на Git for Computer Scientist ; он объясняет, что делает каждый тип объекта в Git, включая ветви и теги.

Бомбы
источник
6

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

Number45
источник
4

просто:

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

Руководство пользователя Git

Бар Horing
источник
4

простой ответ:

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

но

tag: коммит, на который указывает тег, на самом деле тег является снимком этого коммита.

jsina
источник