Git: Использование cherry-pick для копирования тегов из одной ветви в другую - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть ветка MASTER с несколькими коммитами и тегами.Я хотел бы скопировать только теги из MASTER в ветку RELEASE (и никаких других коммитов).

Сначала я создал пустую ветку MASTER и зафиксировал ее только с помощью сообщения.Затем я создал пустую ветку RELEASE.Я добавил несколько коммитов в MASTER со следующим содержимым:

  • C1: файл1
  • C2: файл1, файл2
  • C3: файл1, файл2, файл3

В MASTER я создал тег T1 с C2 (который содержит file1 и file2). Теперь я хотел бы скопировать тег T1 в ветку RELEASE.Казалось, что мне нужно использовать cherry-pick, чтобы сделать это.

Сначала я отмечу SHA-ID тега T1 в MASTER.Затем я делаю:

  • git checkout RELEASE
  • git cherry-pick [SHA-ID T1]

Success, но ветка RELEASE теперь показывает толькоfile2.Разве он не должен отображать содержимое тега T1, то есть как file1, так и file2?

Опять же, моя цель состоит в том, чтобы теги MASTER (и никаких других коммитов) отображались в RELEASE.Это возможно?Заранее спасибо.

1 Ответ

0 голосов
/ 20 декабря 2018

Давайте начнем с этого:

... моя цель состоит в том, чтобы только теги MASTER (и никаких других коммитов) отображались в RELEASE

Эта цель делаетнет смысла в Git.В Git все имена ссылок существуют вне набора коммитов.Более того, между именами нет контейнера / содержимого (с одним ограничением, унаследованным от того, как Git реализует эти имена в настоящее время).То есть имена A и B полностью независимы друг от друга.Имена feature/X и feature/Y также полностью независимы друг от друга.Внесение каких-либо изменений, в том числе создание нового имени или удаление старого, не влияет ни на одно другое имя.

(за исключением того, что, получив имя feature/X или feature/Y, вы можетебольше не использовать имя feature. Это имя теперь "занято" частью feature/ двух других имен. Вы можете продолжать использовать feature/ для хранения большего количества имен, и вы можете использовать featurбез окончательного e, но вы не можете создать имя feature для идентификации объекта, поскольку feature/ существует из-за feature/X и / или feature/Y.)

Имена тегов не содержатсяв филиалах.Имена ветвей не содержатся в тегах.Все они являются отдельными сущностями, существующими рядом друг с другом.Это зависит от вас, чтобы организовать их.Одним разумным способом является использование этих слешей: feature/<em>name</em> - это хорошее короткое имя для ветви, для которой вы и / или другие люди разрабатывают новую функцию, имя (или кодовое имя) которой равно name.Имена ветвей в форме relbranch/<em>name</em> могут быть хорошими короткими именами для организации коммитов, которые войдут в конкретный выпуск, чье имя (или кодовое имя) равно name.Когда одна конкретная фиксация, нацеленная на какой-либо выпуск, была проверена QA и в настоящее время поставляется, имя тега в форме releases/<em>name</em> может быть хорошим коротким именем для этого выпуска.

(Обратите внимание, что git for-each-ref, внутренняя команда Git для работы со ссылками в целом, особенно рада компонентам имен, разделенным косой чертой: git for-each-ref refs/tags/releases перебирает все теги в refs/tags/releases/*, например.)

Подробнее о тегеи имена ветвей

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

Это также верно для имен ветвей., но с парой важных отличий:

  • Ожидается, что имя ветви изменит со временем.То есть после того, как вы сделали коммит C1 (каким бы ни был его фактический хэш-идентификатор), имя master - это имя коммита C1.Но затем процесс создания коммита C2, находясь на master, , изменил имя master на имя коммита C2.Когда вы сделали C3, Git снова изменил master, поэтому теперь он идентифицирует коммит C3.

  • Тег имя , как ожидается, будет постоянным.То есть, если вы создаете тег T , имена которого фиксируют C2, каждый Git везде - ну, каждый репозиторий Git, который вы когда-либо подключаетесь к своему Git-репозиторию, прямо или косвенно - может предполагатьс этого момента T означает «commit C2».Если вы в своем хранилище извлекаете тег T и создаете новый T , имена которого передают C3, все другие Git-репозитории верны, если они продолжают переводитьимя T до C2.(Они также являются правильными, если они переходят на C3, но их не нужно менять.)

  • Имена тегов могут указывать косвенно на коммиты через объект тега.Git называет этот тип тегов аннотированным тегом .Объект тега может хранить немного дополнительной информации, такой как ключ подписи PGP, говорящий Я, подписавший, проверил, что этот конкретный коммит действителен и должен использоваться. Это относится к v2.20.0 вGit-репозиторий для Git, например:

    $ git cat-file -p v2.20.0
    object 5d826e972970a784bd7a7bdf587512510097b8c7
    type commit
    tag v2.20.0
    tagger Junio C Hamano <gitster@pobox.com> 1544329907 +0900
    
    Git 2.20
    -----BEGIN PGP SIGNATURE-----
    
    iQIzBAABCAAdFiEE4fA2sf7nIh/HeOzvsLXohpav5ssFAlwMmrMACgkQsLXohpav
    5sv6pg//VIRzIkTz+DQ4ITzWXpH41lGjhsbSN554a/Kj5W1RvHiQmzpv5HDM65vr
    Dr9DqYiP3HBOPElUTxT5iS2qgsajrRZ1yvKMEnb+YxLbix0NhkvdhJxHmsTUYmEH
    SOve1ddx9spKHEdRjgw6eyoTiG5yQgcea7XkdATeTYeJzZIfMcrXVR920ZjUi9dK
    DRambd/KGYFIPftN0EdVCVPUDrNlKvmK3RhS7arZUxFBxSGDVzGiStK0r2aSw0lb
    gT27Ygy+cz0StWL2q4kV4ghPhjpAv9QqypNNADRg9ZxDhY446V2flU67oV0PLCm/
    E4GmgkjGOphQOujWJv6Uz+6F4E1DvGx9Wt78Xbl3kXZruyhwIv/7yk53nUPxtaI5
    PjBqy+2vJPmZoUONH3/zSYlGW4ZwURatXTDe3FOK15Eq3EV+IpbRGhpuu4Ju9U3c
    L1dpTFdauiKJFuSNkrsdrJPhpX2nbgYl3PloxHWAhPzoqFGib4reRqrm12lczpRp
    BytNhs8RWwR+4CZXAFYtITFEdBLhHvWodklYnGfTFlMKs/OZ4S+XNS2LOb6Wjc3S
    EFF4U87QGnHm6vCREpKwVOMroAEOUXsrbHc3tzxrX16GlXHNWYI/fgAkD6twffE8
    GEIclUQ7v/fRFlmznDJKGOoWVDTUzwLCVeb36lmpd6w+CpRm7cc=
    =1E0P
    -----END PGP SIGNATURE-----
    

    (Аналог аннотированного тега - легкий тег , который просто указывает непосредственно на коммит. По умолчанию git describeигнорирует легкие теги, используя только аннотированные, чтобы придумать более понятное для человека имя для некоторого необработанного хэша коммита.)

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

Информация о cherry-pick

Обратите внимание, что git cherry-pick делает копирование коммитов.Для этого сначала преобразует фиксацию в набор изменений.(Это объяснение немного ручное, и в нем игнорируется тот факт, что cherry-pick реализован с помощью механизма слияния, но достаточно для размышлений о проблемах.) Помните, что фиксация сохраняет снимок каждогофайл, в том виде, в каком он был, когда вы (или кто-либо другой) сделал этот коммит.

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

Чтобы преобразовать коммит (снимок) в набор изменений, Git должен сравнить его со своим непосредственным предшественником.Например, предшественником C3 является C2, поэтому, сравнивая снимок в C2 со снимком в C3, Git может сказать вам, что изменило с C2 на C3.

Для вишни-выберите, затем вы начнете с проверки некоторого существующего коммита (кроме C2 или C3, конечно).Как правило, это происходит через git checkout <em>name</em>, используя имя ветви, в которой разрабатывается данная конкретная версия.Затем вы говорите Git: Сначала выясните, что изменило в C3 по сравнению с C2.Затем внесите те же изменения в мой текущий коммит not-C2 not-C3 и используйте результат, чтобы сделать новый коммит.

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

...