Computer screen displays "vibe vibe coding" text.

Apps

VS Code добавляет «Co-Authored-by Copilot» к каждому коммиту

Расширение Copilot для VS Code незаметно добавляет трейлер Co-Authored-by в ваши коммиты — даже если вы написали каждую строку самостоятельно. Вот как именно это остановить.

TLDR Расширение GitHub Copilot для VS Code автоматически добавляет трейлер Co-authored-by: GitHub Copilot к сообщениям коммитов, когда оно участвует в их генерации — а иногда и в тех случаях, когда не участвует. Это затрагивает записи об авторстве, историю вкладов в open-source проекты и потенциально политику работодателей в отношении интеллектуальной собственности. Нейтрализовать это можно с помощью git-хука, изменения настроек VS Code или глобального правила gitconfig — у каждого подхода есть свои компромиссы.

Если вы недавно заглядывали в свой git log и заметили незнакомую строку в конце сообщений коммитов, которые написали полностью самостоятельно, — вам не кажется. GitHub Copilot — точнее, расширение Copilot для VS Code — тихо проставляет своё имя в коммиты как соавтор, независимо от того, изменил ли он хоть одну строку в этом пуше. Это не заговор, а система атрибуции по принципу «отказ по умолчанию», на которую большинство разработчиков никогда осознанно не соглашались. Далее — точное описание того, как работает это внедрение, почему GitHub так сделал, и — что наиболее полезно — какие именно настройки, хуки и конфиги заставят это прекратиться.

Панель управления исходным кодом VS Code с генерацией сообщений коммитов Copilot


Как выглядит трейлер

Прежде чем что-то исправлять, полезно точно понять, с чем вы имеете дело. Внедряемый текст — стандартный трейлер git-коммита: пара «ключ — значение», добавляемая после пустой строки в конце тела сообщения коммита. Он следует тому же формату, что используется git interpret-trailers и такими инструментами, как Gerrit и собственная инфраструктура слияния GitHub:

feat: добавить поток аутентификации пользователей

Реализовать JWT-вход с ротацией refresh-токенов.

Co-authored-by: GitHub Copilot <github-copilot[bot]@users.noreply.github.com>

Последняя строка — то, что внедряет Copilot. Адрес github-copilot[bot]@users.noreply.github.com является реальным аккаунтом бота GitHub, а это означает, что граф контрибуций GitHub и движок атрибуции коммитов фактически регистрирует это как соавторство — не комментарий и не метаданные, которые можно проигнорировать. Это полноценный объект git, навсегда встроенный в историю коммитов после пуша.

Где это появляется

  • Просмотр коммитов на GitHub: у коммита будет отображаться значок «Co-authored by GitHub Copilot» рядом с вашим аватаром.
  • git log --format=full: трейлер появится в полном теле коммита.
  • git shortlog: в зависимости от способа обработки Copilot может отображаться как контрибьютор в статистике проекта.
  • Граф контрибьюторов GitHub: бот-аккаунт может зарегистрироваться как контрибьютор вашего репозитория.
Warning После того как вы запушили коммит с этим трейлером в общий удалённый репозиторий, переписывание истории (через git rebase -i или git filter-branch) для его удаления является деструктивной операцией, которая потребует принудительного пуша и нарушит локальную историю коллег. Профилактика значительно проще, чем устранение последствий.

В каких коммитах это встречается чаще всего

Внедрение наиболее агрессивно при использовании функции Создать сообщение коммита — значка с блёстками (✨) на боковой панели Source Control. Нажмите его — Copilot составит сообщение, и трейлер соавтора будет добавлен ещё до того, как вы подтвердите. Но разработчики сообщают, что трейлер появляется и в коммитах с сообщением, написанным вручную, — особенно если Copilot Chat был активен в этом сеансе и использовался для генерации кода в проиндексированных файлах.


Механизм внедрения

Расширение GitHub Copilot для VS Code глубоко интегрируется с API Source Control Manager (SCM) VS Code. Когда вы индексируете файлы и открываете поле ввода сообщения коммита, Copilot регистрируется как провайдер поля ввода SCM и может программно заполнять или изменять это текстовое поле — в том числе добавлять трейлеры прежде, чем вы наберёте хоть один символ.

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

Как SCM API VS Code это делает возможным

VS Code предоставляет vscode.scm.inputBox и связанные API, которые расширения могут использовать. Расширение Copilot применяет их для:

  1. Наблюдения за тем, какие файлы проиндексированы, и их диффами.
  2. Определения того, был ли Copilot вызван (или просто активен) во время редактирования этих файлов.
  3. Генерации сообщения коммита через Copilot API.
  4. Внедрения сообщения — включая трейлер — в поле ввода коммита перед отправкой.

Внедрение происходит на стороне клиента в VS Code, а не на серверах GitHub, а значит, серверные правила или защиты веток не могут перехватить его до того, как оно попадёт в историю.

Info Это поведение отличается от серверной атрибуции Copilot для pull request на GitHub. То, что делает расширение VS Code, — это клиентское внедрение текста в поле сообщения коммита, совершенно другой путь в коде.

Происходит ли это без использования функции генерации?

Да — и именно это больше всего раздражает разработчиков. Пользователи сообщают о появлении трейлера даже когда:

  • Они написали сообщение коммита вручную (не через кнопку с блёстками).
  • Проиндексированные изменения были написаны вручную на 100%.
  • Copilot Chat был открыт, но не использовался для текущей задачи.

Эвристика расширения для определения «Copilot был задействован» размытая. Если Copilot был активен во время сеанса редактирования любого файла в диффе — даже если вы отклоняли каждое предложение — он всё равно может добавить трейлер. В этом и суть претензий: это не атрибуция за реальный вклад AI, это атрибуция по факту близости.


Почему это важно не только с эстетической точки зрения

Посторонний соавтор в git log может показаться косметическим неудобством, но есть реальные последствия, которые стоит понять, прежде чем решать, насколько срочно действовать.

Разработчик просматривает git log в терминале с коммитами с соавторством

Интеллектуальная собственность и политика работодателей

Многие работодатели — особенно в регулируемых отраслях, таких как финансы, здравоохранение и оборонные контракты — имеют чёткую политику интеллектуальной собственности в отношении кода, созданного AI. Строка Co-authored-by: GitHub Copilot в коммите к проприетарной кодовой базе — это задокументированная запись о том, что инструменты AI участвовали в создании этого кода. Даже если Copilot автодополнил только закрывающую скобку, этот трейлер создаёт след аудита, которым юридическим отделам, возможно, придётся заниматься.

Если ваша компания явно не разрешила использование Copilot для продакшн-кода, этот трейлер создаёт риск, на который вы не подписывались.

Последствия для лицензирования open-source

Правовой статус кода, созданного AI, и его совместимость с копилефт-лицензиями (GPL, AGPL) ещё не урегулированы. Проекты со строгой политикой принятия вкладов могут отклонить или потребовать переписать историю для коммитов, содержащих атрибуцию Copilot, — FSF и другие организации опубликовали свои позиции по этому вопросу. Если вы поддерживаете open-source проект с контрибьюторами, которые ожидают чистой провенанс, трейлеры Copilot в вашей истории усложняют ситуацию.

Статистика контрибьюторов и портфолио для найма

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

Warning Если вы фрилансер или консультант, чьи клиенты проверяют историю git как часть приёмки работ, атрибуция Copilot в репозиториях, принадлежащих клиентам, может вызвать вопросы по контракту, которых вы предпочли бы избежать.

Четыре способа остановить это

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

Вариант 1 — Настройки расширения VS Code

Наиболее прямой путь — отключить это поведение в настройках VS Code. Откройте настройки (Ctrl+, или Cmd+,), затем найдите «copilot commit». Вы ищете параметры расширения GitHub Copilot, связанные с генерацией сообщений коммитов и атрибуцией соавтора.

В settings.json соответствующий путь конфигурации выглядит так:

{
  "github.copilot.chat.generateCommitMessage.enabled": false
}

Полное отключение генерации сообщений коммитов останавливает внедрение у источника — Copilot вообще не будет заполнять поле ввода коммита, и возможности добавить трейлер не будет. Если вы всё же хотите использовать AI-генерацию сообщений коммитов, но без строки атрибуции, некоторые версии расширения предоставляют отдельный переключатель именно для трейлера соавтора. Перейдите в Extensions > GitHub Copilot > Settings на боковой панели VS Code, чтобы проверить, что доступно в вашей установленной версии, — точные названия настроек менялись в разных выпусках расширения Copilot.

Tip В интерфейсе настроек VS Code рядом с настройками расширения отображается его текущая версия. Если у вас старая сборка Copilot, обновление расширения может дать более детальное управление поведением атрибуции — Microsoft реагирует на отзывы сообщества по этому вопросу.

Вариант 2 — Git-хук (наиболее надёжный)

Хук prepare-commit-msg запускается автоматически перед открытием редактора сообщений коммита и может точечно удалять трейлер Copilot независимо от того, как он туда попал. Этот подход работает независимо от VS Code, выдерживает обновления расширений и применяется к любому git-клиенту, используемому в репозитории.

Создайте файл хука по пути .git/hooks/prepare-commit-msg:

#!/bin/sh
# Strip GitHub Copilot co-author trailer from commit messages
sed -i '/^Co-authored-by: GitHub Copilot/Id' "$1"

Затем сделайте его исполняемым:

chmod +x .git/hooks/prepare-commit-msg

Для командного решения используйте общую директорию хуков, зафиксированную в репозитории, и настройте git на её использование:

# В .gitconfig или локальном конфиге репозитория
git config core.hooksPath .githooks

Затем зафиксируйте ваш хук в .githooks/prepare-commit-msg с тем же содержимым выше. Каждый разработчик, клонировавший репозиторий и выполнивший git config core.hooksPath .githooks (или при автоматизации в скрипте настройки), получит поведение по удалению трейлера.

Info Флаг -i в sed редактирует файл на месте. На macOS BSD sed требует явного расширения резервной копии: sed -i '' '/^Co-authored-by: GitHub Copilot/Id' "$1". Добавьте условную конструкцию shell, если ваша команда использует и Linux, и macOS.

Вариант 3 — Отключить Copilot для рабочего пространства

Если ваша озабоченность связана с конкретным репозиторием (например, клиентским проектом или open-source репозиторием со строгими правилами провенанса), можно полностью отключить Copilot для этого рабочего пространства, не трогая глобальные настройки. В корне репозитория создайте или отредактируйте .vscode/settings.json:

{
  "github.copilot.enable": {
    "*": false
  }
}

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

Вариант 4 — Глобальное правило очистки gitconfig

Если трейлер проникает в коммиты из нескольких инструментов и сред (не только VS Code), глобальный хук prepare-commit-msg в шаблоне git домашней директории охватывает всё:

# Установить глобальную директорию шаблонов хуков
git config --global init.templateDir ~/.git-templates

# Создать директорию и хук
mkdir -p ~/.git-templates/hooks
cat > ~/.git-templates/hooks/prepare-commit-msg << 'EOF'
#!/bin/sh
sed -i '/^Co-authored-by: GitHub Copilot/Id' "$1"
EOF
chmod +x ~/.git-templates/hooks/prepare-commit-msg

Любой новый репозиторий, который вы инициализируете или клонируете после этого, автоматически унаследует этот хук. Для существующих репозиториев выполните git init в корне репозитория — это безопасно для существующих репозиториев и скопирует хуки шаблона, не затрагивая историю.


Сравнение вариантов

Метод Область применения Удаляет трейлер Сохраняет автодополнение Подходит для команды Выдерживает обновления расширения
Настройка VS Code (отключить генерацию) Глобально или рабочее пространство Да Нет Через коммит settings.json Да
Хук prepare-commit-msg (локальный) Для репозитория Да Да Через паттерн .githooks/ Да
Отключение для рабочего пространства (copilot.enable) Для репозитория Да Нет Через .vscode/settings.json Да
Глобальный хук шаблона git Все репозитории (новые и будущие) Да Да Нет (уровень пользователя) Да
Полное отключение расширения Copilot Глобально Да Нет Н/Д Н/Д

Лучший вариант для тех, кто хочет сохранить автодополнение Copilot: хук prepare-commit-msg + глобальный шаблон.

Лучший вариант для команд с общей политикой: зафиксированная директория .githooks/ с документацией по настройке.

Лучший вариант для чувствительных клиентских репозиториев: copilot.enable: false на уровне рабочего пространства, зафиксированный в .vscode/settings.json.


Очистка коммитов, в которых это уже есть

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

# Интерактивный rebase для редактирования последних коммитов
git rebase -i HEAD~10

# Для каждого затронутого коммита отметьте его как 'reword' и удалите строку трейлера
# Или используйте filter-branch для массовой очистки:
git filter-branch --msg-filter \
  'sed "/^Co-authored-by: GitHub Copilot/Id"' \
  HEAD~20..HEAD

После перезаписи потребуется принудительный пуш:

git push --force-with-lease origin ваша-ветка
Warning --force-with-lease безопаснее --force, потому что откажет в пуше, если кто-то другой запушил в ветку после вашего последнего fetch. Это не защищает публичные общие ветки — координируйтесь с командой перед выполнением этого на чём-либо, кроме личной фиче-ветки.

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

Настройки репозитория GitHub с правилами защиты веток


Краткий чеклист

Пройдите по этому списку в порядке, соответствующем вашей ситуации:

  1. Убедитесь, что видите трейлер: выполните git log --format=full -5 и проверьте наличие Co-authored-by: GitHub Copilot в конце тела любого коммита.
  2. Установите хук prepare-commit-msg в затронутом репозитории — это наименее трудоёмкое и наиболее надёжное исправление.
  3. Проверьте настройки Copilot в VS Code: откройте настройки, найдите «copilot commit» и отключите генерацию сообщений коммитов, если не пользуетесь кнопкой с блёстками.
  4. Для чувствительных репозиториев: добавьте .vscode/settings.json, отключающий Copilot для этого рабочего пространства, и зафиксируйте его, чтобы коллеги унаследовали настройку.
  5. Для командных сред: создайте директорию .githooks/, добавьте скрипт prepare-commit-msg, зафиксируйте его и добавьте git config core.hooksPath .githooks в инструкции по настройке проекта или Makefile.
  6. Установите глобальный шаблон git, если работаете со многими личными репозиториями и хотите решение «настрой и забудь».
  7. Проверьте последние коммиты в общих ветках: используйте git log --grep="Co-authored-by: GitHub Copilot" --oneline для поиска затронутых коммитов, прежде чем решить, нужна ли очистка истории.
  8. Убедитесь, что исправление работает: проиндексируйте файл, дайте VS Code открыть диалог коммита, проверьте отсутствие трейлера перед подтверждением коммита.

Источники и дополнительное чтение

  • GitHub Docs — Commit Trailer Attribution — Официальная документация GitHub о том, как работают трейлеры соавторов в графе контрибуций GitHub и что означает формат Co-authored-by для статистики репозитория и атрибуции в pull request.

  • Список изменений расширения GitHub Copilot для VS Code (marketplace.visualstudio.com) — Примечания к выпускам расширения Copilot документируют введение генерации сообщений коммитов и последующие изменения в поведении атрибуции; ищите версии с конца 2023 года.

  • git-scm.com — Документация по githooks — Авторитетный справочник по хуку prepare-commit-msg, его контексту вызова, аргументам и взаимодействию с процессом коммита в различных git-клиентах.

  • Software Freedom Conservancy — Копилефт и код, созданный AI — Опубликованный анализ SFC о том, как результаты работы моделей AI взаимодействуют с лицензионными обязательствами GPL и AGPL, актуально для мейнтейнеров open-source проектов, принимающих решение об обработке атрибуции Copilot в своих проектах.

  • GitHub Community Forum — «Copilot добавляет Co-authored-by без моего ведома» — Продолжающиеся дискуссионные ветки с реальными случаями поведения внедрения, подтверждёнными пользователями обходными решениями и ответами сотрудников GitHub о задуманном дизайне в сравнении с описанными пограничными случаями.