Avatar ·

Нужно ли коммитить go.sum файл в Git репозиторий?

Привет! Я начал изучать Go и перехожу с использования GOPATH на Go Modules. У меня есть проект, который использует несколько внешних зависимостей. Я инициализировал модуль командой `go mod init` и добавил зависимости через `go get`. В результате появились два файла: `go.mod` и `go.sum`. Я понимаю, что `go.mod` нужно коммитить — это как `package.json` или `requirements.txt`. Но с `go.sum` всё не так очевидно. Я вижу, что это огромный файл с хешами, который постоянно меняется. Например, сейчас у меня в проекте есть зависимость `github.com/gin-gonic/gin v1.9.1`, и `go.sum` содержит десятки строк с хешами для этой и других библиотек. Мой тимлид говорит, что `go.sum` нужно коммитить, чтобы обеспечить воспроизводимость сборок. Но я читал, что некоторые разработчики не коммитят его, потому что он большой и его можно перегенерировать. К тому же, в некоторых CI/CD пайплайнах я видел, что они запускают `go mod download` и всё работает. Подскажите, пожалуйста, какой правильный подход? Нужно ли добавлять `go.sum` в `.gitignore`? Есть ли какие-то риски, если я его не закоммичу? Пример моего `go.mod`: ``` module myapp go 1.21 require ( github.com/gin-gonic/gin v1.9.1 github.com/go-sql-driver/mysql v1.7.1 ) ``` Буду благодарен за разъяснение с примерами! <<>>

Да, go.sum нужно коммитить — это критически важно для безопасности и воспроизводимости

Короткий ответ: всегда коммитьте go.sum. Это не опционально, а рекомендованная практика от команды Go и сообщества. Вот почему.

Что такое go.sum на самом деле?

go.sum — это не список зависимостей (эту роль выполняет go.mod), а манифест целостности. Он содержит криптографические хеши (SHA-256) для каждой версии каждой зависимости, включая все транзитивные зависимости. Пример строки:

github.com/gin-gonic/gin v1.9.1 h1:4C3sGJ9Q6pC8u0aH4F0g6b/GwX3fqWgMmHPCNpIk6Y=
github.com/gin-gonic/gin v1.9.1/go.mod h1:7C7V9D9U9pC0o8YlW3N2k1T1JxX3fBQo5i5v7QnP8s=

Первая строка — хеш содержимого модуля (исходный код, файлы). Вторая строка — хеш только его go.mod файла. Когда вы запускаете go build, Go проверяет, что загруженный модуль соответствует этим хешам.

Зачем это нужно?

  • Безопасность: Если злоумышленник подменит код зависимости, хеш не совпадёт, и сборка упадёт с ошибкой. Без go.sum вы не узнаете, что зависимость изменилась.
  • Воспроизводимость: Другой разработчик или CI-система получат те же самые файлы, что и вы. Даже если автор библиотеки пересоберёт релиз с другим содержимым, ваш go.sum защитит от этого.
  • Работа в офлайне: После go mod download все зависимости кешируются. go.sum позволяет проверить целостность кеша без доступа к интернету.

Что будет, если не коммитить go.sum?

Представьте сценарий:

  1. Вы закоммитили go.mod без go.sum.
  2. Коллега клонирует репозиторий и запускает go mod download.
  3. Go загрузит зависимости, но не сможет проверить их целостность — он просто доверится тому, что скачал. Если в репозитории GitHub произошла подмена, коллега получит вредоносный код.
  4. Более того, Go может перегенерировать go.sum с новыми хешами, которые будут отличаться от ваших. Это приведёт к "ложному" конфликту в Git, если вы потом попытаетесь синхронизироваться.

Пример: допустим, вы используете библиотеку github.com/go-sql-driver/mysql v1.7.1. Без go.sum при следующей сборке Go может скачать v1.7.1, но если автор удалил релиз и пересоздал его с другим содержимым (например, фиксом бага), вы получите неожиданное поведение. С go.sum сборка просто сломается, предупреждая вас об аномалии.

Мифы и заблуждения

  • "go.sum большой, не хочу засорять репозиторий" — Файл текстовый и обычно занимает 10-50 КБ для среднего проекта. Это ничто по сравнению с размером зависимостей.
  • "Его можно перегенерировать через go mod tidy" — Да, но для этого нужно доверять источнику, с которого вы скачиваете модули. Если ваш proxy-сервер скомпрометирован, вы получите поддельные хеши.
  • "CI сам всё скачает" — CI скачает, но без проверки целостности. Это снижает уровень безопасности.

Практические рекомендации

  1. Добавьте go.sum в Git и коммитьте его вместе с go.mod.
  2. Никогда не редактируйте go.sum вручную — это делает только Go.
  3. Используйте go mod verify в CI, чтобы убедиться, что кеш не повреждён.
  4. Если вы используете приватные репозитории, настройте GONOSUMCHECK или GONOSUMDB для тех модулей, которые не должны проверяться через публичный checksum database.

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

<<>>

Когда можно не коммитить go.sum (исключения из правил)

Хотя общее правило — коммитить, есть редкие ситуации, когда это не обязательно:

  • Приватные репозитории с полным контролем: Если все ваши зависимости — ваши же внутренние модули, и вы полностью контролируете их версии и целостность (например, через внутренний proxy), то go.sum можно не коммитить. Но это рискованно.
  • Временные проекты или прототипы: Если проект живёт 2 дня и его никто больше не будет собирать, можно не заморачиваться. Но лучше выработать привычку коммитить всегда.
  • Использование vendor-директории: Если вы коммитите папку vendor/ (через go mod vendor), то go.sum становится менее критичным, потому что код зависимостей уже в репозитории. Однако Go всё равно использует go.sum для проверки vendor-модулей при сборке, так что лучше коммитить и его.

Лично я рекомендую придерживаться правила: если есть go.mod — коммить и go.sum. Это защитит вас от головной боли в будущем. Даже если сейчас кажется, что проект маленький, через месяц он может вырасти, и отсутствие go.sum станет проблемой.

Кстати, официальная документация Go прямо говорит: "Check the go.sum file into your version control repository along with go.mod." Так что это не просто совет, а best practice.