Как пометить один файл в GIT
Я очень новичок в Git. В настоящее время я пытаюсь ознакомиться с ним, используя его для отслеживания изменений в некоторых файлах Excel, которые я поддерживаю, чтобы отслеживать некоторые постоянные действия, с которыми я связан. Все файлы находятся в одном хранилище. Я хочу пометить каждый файл отдельно с их версиями. Это возможно? До сих пор я обнаружил возможность пометить весь репозиторий. Если то, что я пытаюсь сделать, не так, посоветуйте мне лучшую практику.
Заранее спасибо.
редактировать
Когда я делал это, я намеренно удалил предыдущий тег, чтобы пометить весь репозиторий (так как я не нашел способа пометить отдельные файлы) как v1.0. Поскольку теперь я хочу сбросить имя тега с именем файла и достаточно хорошо понимать, как все должно происходить, как я могу откатить удаление и переименовать предыдущий тег (удаленный тег)?
6 ответов
Теги размещаются на конкретных коммитах, а не на репозитории в целом, как вы предлагаете в своем вопросе.
Один из способов сделать то, что вы предлагаете, это убедиться, что вы фиксируете изменения только в одном файле с каждым коммитом, тогда вы можете пометить этот коммит, например,. file1-v1.0
представлять v1.0 из file1.
Что вы пытаетесь представить, помечая эти коммиты? Это повлияет на любой совет о том, как улучшить ваш процесс.
Технически вы можете пометить содержимое одного файла без его имени. Но такие теги имеют ограниченное использование. Ожидается, что теги будут указывать на коммиты, а специальные теги для некоммитов ведут себя по-разному (вы не можете git оформить такой специальный тег). Поэтому я настоятельно рекомендую никогда не использовать теги без фиксации.
Если вы хотите, чтобы только некоторые файлы были помечены, может быть лучше использовать для них отдельный репозиторий или хотя бы разные ветви, поскольку git всегда просматривает полное дерево своих операций.
Если вы все еще настаиваете на создании такого специального тега, вы делаете:
> git ls-tree HEAD
040000 tree 2c186ad49fa24695512df5e41cb5e6f2d33c119b bar
100644 blob 409940768f2a684935a7d15a29f96e82c487f439 foo.txt
> git tag my-bar-tree 2c186ad49fa24695512df5e41cb5e6f2d33c119b
> git tag my-foo-file 409940768f2a684935a7d15a29f96e82c487f439
Вы можете пометить только коммит, например, определенный снимок в истории вашего хранилища. Тем не менее, git хранит файлы в виде больших двоичных объектов, и вы можете использовать git notes для добавления заметки в большой двоичный объект, например:
$ git ls-tree HEAD
100644 blob 252f7c7df5bd181536a6c9d0f9c371ce1a5dd042 .gitignore
100644 blob 8150ada74aba86c983ac3f8f63ab26aaa76fdcb7 README
100644 blob c4b1ff6dcb2a8e50727df21ced8d2872cd91af79 TODO.txt
$ git notes add -m "Adding a note to TODO" c4b1ff6dcb2a8e507
$ git notes show c4b1ff6dcb2a8e507
Adding a note to TODO
Однако обратите внимание, что это примечание (без каламбура:)) прикреплено только к этому BLOB-объекту, поэтому всякий раз, когда файл изменяется, создается новый BLOB-объект (с другим значением хэша sha1), и новый BLOB-объект не будет иметь этого примечания.
Вы должны действительно изучить наличие отдельных веток, которые отслеживают изменения в определенных файлах. Вы должны быть в состоянии работать с этим.
Не напрямую, нет.
Тег - это указатель на конкретную ревизию хранилища. Отдельные файлы не имеют версий, отличных от версии хранилища. Если вы хотите использовать разные версии, вы можете создать отдельный репозиторий для каждого файла, иметь отдельную ветвь для каждого файла или использовать другой инструмент, ориентированный на файлы (например, RCS - хотя в нем отсутствуют многие приятные функции). мерзавец имеет).
Если файлы вообще связаны, вы, как правило, хотите пометить конкретную версию группы из них. Если это не так, вы все равно можете пометить всю группу версией каждого файла, измененной в этой ревизии. Ограничение изменений одним файлом для каждой ревизии может упростить управление этим процессом.
Это не ответ на исходный вопрос, а ответ на один из комментариев к этому исходному вопросу.
git теги коммитов. Не файлы. Можете ли вы рассказать нам, что вы хотите сделать с этими «тегами»? Я думаю, что тогда был бы возможен более адекватный ответ. — Нуфаль Ибрагим
Я публикую этот расширенный комментарий как псевдоответ
- потому что комментарии stackoverflow имеют ограниченное форматирование.
- и потому что я не считаю уместным добавлять свое объяснение того, почему я хочу пометить один файл или подмножество к вопросу OP, если это не то же самое
КРАТКИЙ ОТВЕТ:
Когда я делаю различия между tag-for-code.txt--update-by-jim-April1st и tag-for-code.txt--original-version-by-joe, я хочу видеть различия только для my-lib/ импорт/новый-модуль/code.txt . Или, возможно, my-lib/import/new-module . Я не хочу видеть различия для my-lib/import/module1 ,
который предположительно полностью независим[*] от *my-lib/import/new-module/code.txt . Нет, я не хочу знать, какие части я должен отфильтровать. Я могу этого не знать, не копнув глубже.
Я понимаю, что теги git предназначены для коммитов, а коммиты — это, по сути, снимки всего репозитория. Поэтому я просто прошу обходной путь, который позволил бы мне с удобством сказать
Например, возможно, мне следует создать гипотетический тег подмножества, чтобы создать файл, содержащий список имен файлов и идентификатор фиксации репо. Таким образом, инструменты, использующие такие теги подмножества, будут фильтровать только информацию, относящуюся к списку имен файлов в соответствующих файлах тегов. Или, возможно, просто blob-ID. Что бы ни.
Кто-нибудь получил BKM для этого?
===
Я публикую это как псевдоответ, потому что я долго страдал от интеллектуальной боли из-за отсутствия тегов одного файла или подмножества в git. Наверняка есть эквивалент git? Хотя я подозреваю, что не из-за поразительного количества нецелевых ответов, часто в форме "почему ты хочешь это сделать?"
Некоторые другие системы управления версиями имеют теги как всего репо, так и отдельных файлов или подмножеств. AFAICT git - нет. Без ограничения общности я приведу пример из CVS, хотя эти концепции применимы и к DVCS.
Краткое изложение того, почему вам нужна маркировка отдельных файлов и подгрупп файлов, а также маркировка всего репо
Мы все согласны с тем, что игры с символическими тегами хороши. Верно?
В старые недобрые времена были только одиночные файловые теги. Хотя обычно вы можете применить один и тот же тег к группам файлов, не гарантируется, что вы примените один и тот же тег ко всему репозиторию.
Поэтому, если вы сделали checkout -rTestsRunTag, ожидая, что сможете успешно собрать и запустить тесты, это может привести к сбою, потому что какой-то файл, от которого вы не знали, что вы зависели, не был помечен TestsRunTag.
Отсюда предпочтение целых тегов репозитория. Теги, которые применяются к моментальному снимку всего репозитория. Будем надеяться, что если вы проверите такой полный тег репозитория, вы гарантированно сможете выполнить успешную сборку. Верно? ...
На самом деле не правильно. Поместили ли вы свои инструменты сборки, компилятор и т. д. в свой репозиторий?
Тем не менее, тегирование всего репозитория было очень хорошим шагом к воспроизводимым сборкам и тестам.
тем не менее ^2, VCS, которые применяют только теги всего репозитория, выбрасывают ребенка вместе с водой из ванны.
По-прежнему существует потребность в маркировке отдельных файлов. Чаще всего групповая пометка файлов, где группа не является всем репозиторием. Обычно поддерево каталога или, если вы связаны с такими вещами.
По сути, вам нужна такая маркировка подмножества, когда тег имеет отношение только к подмножеству. Когда тег не имеет значения и даже сбивает с толку весь репозиторий.
Или когда использование всего тега репо неудобно.
Как я пытаюсь объяснить в приведенном ниже примере, когда я делаю различия между code.txt--update-by-jim-April1st и code.txt--original-version-by-joe, я хочу видеть различия только для моей библиотеки. /импорт/новый-модуль/code.txt . Или, возможно, my-lib/import/new-module . но я не хочу видеть различия для my-lib/import/module1 , который якобы полностью независим от *my-lib/import/new-module/code.txt .
Краткий (?) Пример неполной маркировки репо
Вот краткий пример, который только что побудил меня искать и опубликовать это.
У меня есть библиотека в основном независимых вещей. Назовите это моей библиотекой
Я собрал множество модулей со всего Интернета, которые я поместил в эту библиотеку в такие места, как my-lib/import/module1, my-lib/import/module2.
Держите их отдельно друг от друга и от моих собственных вещей, таких как my-lib/my-stuff-my-module1 и так далее.
Я добавляю в эту библиотеку новый модуль, который я импортировал с какого-то сайта. Назовем это my-lib/import/new-module
К сожалению, у этого модуля нет собственной системы контроля версий. Он был размещен в ветке обсуждения с немного разными версиями от разных пользователей. Я не совсем уверен, какую версию я хочу использовать, поэтому я собираюсь добавить несколько из них в свою библиотеку.
WLOG позвольте мне рассказать об одном файле в модуле my-lib/import/new-module/code.txt.
Поэтому я загружаю первую версию, которую нахожу в ветке обсуждения. Поместите его в my-lib/import/new-module/code.txt. Зарегистрируйте его. Я хотел бы дать ему символическое имя, так как это лучше, чем использование хэшей git или числовых номеров версий, таких как 1.1.1.1 CVS. Как насчет, возможно, символического имени "тега" code.txt--original-version-by-joe, хотя я с такой же вероятностью поставлю некоторые даты, такие как исходная дата создания, в имя тега, а также в сообщение фиксации файла, и в идеале больше комментариев, связанных с описанием тега. и мне не нужно иметь имя файла в теге, это просто пример.
Возможно, я использую это некоторое время. Но в конце концов я вижу другую версию в ветке обсуждения. Затем я загружаю первую версию, которую нахожу в ветке обсуждения. Поместите его в my-lib/import/new-module/code.txt. Проверьте это. Я хотел бы дать ему другое символическое имя. Как насчет code.txt--update-by-jim-April1st.
Я надеюсь, что этого достаточно, чтобы показать, почему я хочу, чтобы теги применялись к отдельным файлам или подмножествам файлов, а не ко всему репозиторию.
Теги code.txt--original-version-by-joe и code.txt--update-by-jim-April1st относятся только к модулю my-lib/import/new-module и его файлу my-lib/import /новый-модуль/code.txt . Эти теги нового модуля не имеют отношения к другим модулям, от которых он полностью независим, таким как my-lib/import/module1, my-lib/import/module2, my-lib/my-stuff-my-module1.
Когда я делаю различия между code.txt--update-by-jim-April1st и code.txt-original-version-by-joe, я хочу видеть различия только для my-lib/import/new-module/code. текст . Или, возможно, my-lib/import/new-module . но я не хочу видеть различия для my-lib/import/module1 , который предположительно полностью независим[*] от *my-lib/import/new-module/code.txt .
Примечание: полностью независимых не бывает, но...
Обратите внимание, что я сказал «предположительно полностью независимый». Вот в чем загвоздка. Даже полностью независимые библиотечные модули могут нарушить библиотечную инфраструктуру для сквозных вещей, таких как make-файлы, даже если они никогда не линкуются в одну и ту же программу.
Но, тем не менее, очень удобно иметь разницу по умолчанию между code.txt--update-by-jim-April1st и code.txt-original-version-by-joe только для my-lib/import/new- модуль/код.txt . а не для якобы полностью независимого my-lib/import/module1.
Также удобно иметь способы сказать «diff против моментального снимка всего репозитория в то время, когда был создан тег единственного файла code.txt--update-by-jim-April1st . Это недвусмысленно, если есть только один тег файла.
Незначительные проблемы возникают, если один и тот же тег применяется к версиям нескольких файлов, которые не находятся в одном снимке всего репозитория (например, git commit). но вы можете справиться с этим.
Почему бы не использовать модули?
Я слышу, как некоторые идиоты , гм, люди с меньшим воображением говорят: «Почему бы просто не использовать модули?» Речь идет не об общем программном разделении программы на модули и подмодули, а о модулях и подмодулях конкретно в системе контроля версий, вроде модулей и подмодулей git.
Хорошо, я просто использовал модули в приведенном выше примере, чтобы упростить обсуждение.
Модули, определенные системой контроля версий, имеют некоторые накладные расходы. Вы должны настроить вещи априори. Это часто не достаточно хорошо.
Многие системы начинаются как один файл в каком-то большом родительском репозитории, когда они не считаются отдельным модулем. а затем превратиться в отдельный модуль. Черт возьми, они часто начинаются как отдельная функция в big_file_of_many_functions.c Затем вы понимаете, что эта функция и/или некоторые близкие родственники должны быть в отдельном файле, например foo.c , и если вы работаете на C/C++, почти всегда нужен заголовочный файл foo.h . в конце концов вы понимаете, что было бы действительно лучше, если бы существовал отдельный каталог foo/, содержащий foo/foo.c и foo/foo.h . И в конце концов вы можете добавить foo/Makefile, foo/tests/test1.py
и где-то в процессе эволюции от функции в более крупном файле других функций к поддереву вы решаете дать ему модульный подмодуль системы контроля версий.
Замечательно. Но было бы неплохо иметь способы ссылки (а) на этот набор связанных вещей в большом репозитории (б) и две версии этого набора связанных вещей.
Я говорю снова:
Модули, определенные системой контроля версий, имеют некоторые накладные расходы. Значительные накладные расходы.
Это не только я говорю. Это во многом связано с дискуссией о монорепо и мультирепо, например https://johnclarke73.medium.com/mono-or-multi-repo-6c3674142dfc . Некоторые очень важные разработчики программного обеспечения и компании используют минорепозитории. ИМХО отчасти потому, что git и другие модульные системы VCS доставляют хлопоты .
Рассмотрим дерево, в котором каждое дерево подкаталогов является отдельным модулем.
У меня давно есть личная библиотека. Это глубоко вложенное дерево каталогов. Почти каждое дерево подкаталогов можно рассматривать как независимый модуль. Часто отдельные файлы можно экспортировать по отдельности, например библиотеки только заголовков на C или C++. обычно я предпочитаю иметь каталог для каждой минимальной логической подсистемы, чтобы можно было иметь отдельные make-файлы и тестовые сценарии.
Я часто делюсь этим кодом с другими проектами, компаниями, работодателями...
Эти другие проекты редко хотят импортировать все мое дерево личной библиотеки. Следовательно, я хочу иметь возможность проверить только подмножество, начиная с одного файла, чаще всего дерева подкаталогов, но иногда и набора деревьев подкаталогов, которые необходимы для совместной работы.
Эти другие проекты часто не хотят использовать мою систему контроля версий. Очень жаль, это жизнь. Но иногда они это делают.
Конечно, современные DVCS имеют очень плохую поддержку проверки произвольных подмножеств. Не хватает поддержки модулей (см. в другом месте). Нехорошо, когда разреженная проверка, иногда называемая разреженной ветвью (хотя терминология быстро запутывается в конкретных системах контроля версий), содержит историю, связанную с элементами, которые не являются частью того, что было извлечено. или, если не то, если ту разреженную ветку, которая не несет лишней истории и объектов доступа, нельзя слить обратно в репозиторий, в котором есть еще объекты в разных частях файловой системы, которые не были проверены, и для истории.
Когда они хотят поделиться системами контроля версий, это действительно сбивает с толку, когда элементы, которые они проверили, помечаются тегами, которые абсолютно не имеют к ним отношения.
Иногда не просто сбивает с толку. Иногда дыра в безопасности.
В любом случае, в этом большом личном монорепозитории мне нравится помечать подмножества, проверенные другими проектами и импортированные обратно из этих других проектов. Но, опять же, эти теги не имеют отношения к вещам, на которые эти другие проекты не хотят смотреть.
например, теги CVS = для каждого файла, но легко сделать несколько файлов
Теги CVS на самом деле определяются для каждого файла. Но это распространено, и CVS упрощает применение одного и того же тега к нескольким файлам, к поддереву репозитория или ко всему репозиторию. например, если вы просто скажете в определенном каталоге, CVS применит тег ко всем файлам в этом каталоге и его подкаталогах. Если вы скажетеcvs tag foo/file1-only bar/file2-only bazz-tree
Конечно, теги CVS не гарантируют согласованности в репозитории, как теги git.
Но это вопрос модели использования. Иногда вам нужны гарантированные теги, согласованные между репозиториями. Иногда нет. Часто используются соглашения об именах, чтобы различать их. И инструменты для определения того, правильно ли применяются эти соглашения об именах, например, если, например, тег предположительно всего репозитория не был применен ко всему.