В чем разница между Git и GitHub для владельцев VPS
Узнайте ключевые различия между системой контроля версий Git и облачным сервисом GitHub. Разберем, зачем хранить код на удаленном сервере и как настроить безопасный деплой.
Что такое GitHub?
GitHub — это хостинговый сервис для хранения Git-репозиториев с веб-интерфейсом для управления ими. Git — это система контроля версий, которая работает на вашем локальном компьютере или сервере. GitHub является коммерческим продуктом, построенным поверх Git; с 2018 года он принадлежит компании Microsoft. Вы можете ежедневно использовать Git, ни разу не открыв GitHub. Однако вы не сможете использовать GitHub без Git.
Это различие критически важно, когда вы начинаете работать с VPS (виртуальным выделенным сервером). Git фиксирует историю изменений ваших конфигурационных файлов и скриптов развертывания. GitHub служит местом для хранения копии этой истории на случай выхода сервера из строя, а также площадкой для сборки и проверки кода. В этом руководстве мы пройдем путь от пустой папки до развертывания проекта на сервере, разбирая каждый новый термин при первом его упоминании.
Что Git делает самостоятельно
Git — это система контроля версий: она фиксирует состояние директории с течением времени, что позволяет отследить, что, когда и почему изменилось. Она была написана в 2005 году для разработки ядра Linux. Git является распределенной системой, что означает, что каждая копия репозитория содержит всю историю изменений. В архитектуре системы нет центрального сервера. Ноутбук коллеги содержит такую же полную копию, как и любой сервер.
Установите Git и укажите свои данные. Git не позволит создать коммит без имени и адреса электронной почты, так как эти данные записываются непосредственно в сам коммит.
sudo apt update && sudo apt install -y git
git --version
git config --global user.name "Your Name"
git config --global user.email "you@example.com"В Ubuntu 24.04 команда git --version выводит git version 2.43.0. Любой релиз последних лет ведет себя аналогичным образом для всех описанных ниже операций.
Пример: репозиторий для файлов развертывания на VPS
Репозиторий, который часто называют просто «репо», — это каталог, за которым следит Git. Он становится репозиторием после выполнения команды git init, которая создает внутри него скрытую папку .git. Именно эта папка и является репозиторием. Удалите .git, и у вас останется обычный каталог без истории изменений.
mkdir vps-deploy && cd vps-deploy
git init -b main
printf '.env\n*.key\n' > .gitignore-b main задает имя первой ветки main. Если пропустить этот параметр, Git выведет длинную подсказку о стандартном имени ветки. .gitignore содержит пути, которые Git никогда не должен отслеживать. Добавьте в него файл с секретными данными сразу же, так как файл, который был закоммичен хотя бы раз, остается в истории даже после удаления. Чтобы правильно его удалить, придется переписывать каждый последующий коммит.
Коммиты: единица истории
Теперь добавьте скрипт и зафиксируйте его.
printf '#!/bin/sh\nsudo systemctl restart caddy\n' > restart.sh
git add restart.sh .gitignore
git commit -m "Add restart script and gitignore"
git log --onelinegit add перемещает изменения в staging area (область подготовленных файлов) — список того, что попадет в следующий коммит. git commit записывает этот список в историю как одну запись. Коммит содержит снимок всех отслеживаемых файлов, сообщение, автора, временную метку и указатель на предыдущий коммит. git log --oneline выводит по одной строке на каждый коммит, каждая из которых начинается с короткого хеша, например a1b2c3d. Этот хеш является именем коммита, и почти любая команда Git принимает его в качестве аргумента.
Пропустите шаг git add, и git commit ответит no changes added to commit (use "git add" and/or "git commit -a"). Ничего не сломалось. Git сообщает, что область подготовленных файлов пуста, поэтому делать снимок нечего. git status — это команда, которую следует запускать, если вы запутались: она показывает текущую ветку, подготовленные изменения и файлы, которые Git видит, но не отслеживает.
Ветви: вторая линия истории
Ветвь (branch) — это подвижный указатель на коммит. main — это ветвь, и для Git она ничем не примечательна. Создание ветви ничего не стоит, так как Git просто записывает новый указатель, а не копирует ваши файлы.
git switch -c add-backup
printf '#!/bin/sh\nrestic backup /srv\n' > backup.sh
git add backup.sh
git commit -m "Add nightly backup"
git switch main
lsПосле git switch main файл backup.sh исчезает из списка. Ничего не было удалено. Файл существует в ветви add-backup, а в main его никогда не было, поэтому Git удалил его из вашей рабочей директории при переключении. Это всех поначалу удивляет. git switch add-backup возвращает его обратно.
Удаленные репозитории: где наконец появляется GitHub
Все, что мы делали до этого момента, выполнялось на одной машине без использования сети. Remote (удаленный репозиторий) — это именованный URL, указывающий на другую копию того же репозитория. GitHub хранит одну из таких копий для вас. Стандартное имя для основного удаленного репозитория — origin.
Создайте пустой репозиторий через веб-сайт GitHub, а затем подключитесь к нему. Предпочтительнее использовать SSH, а не HTTPS: SSH-ключ — это файл, который находится под вашим контролем, и он не имеет срока действия, в отличие от персонального токена доступа (personal access token).
ssh-keygen -t ed25519 -C "vps-deploy"
cat ~/.ssh/id_ed25519.pub
ssh -T git@github.comВставьте выведенный на экран открытый ключ на страницу SSH-ключей в вашей учетной записи GitHub, а затем снова запустите тест. Работающий ключ выдаст ответ Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.. GitHub не предоставляет доступ к оболочке (shell), поэтому такой отказ означает успешное выполнение. git@github.com: Permission denied (publickey). означает, что ваш ключ не был предложен или не был принят, поэтому проверьте, что вы скопировали содержимое файла .pub, а не закрытый ключ, находящийся рядом с ним.
git remote add origin git@github.com:yourname/vps-deploy.git
git push -u origin maingit push отправляет ваши коммиты в удаленный репозиторий. -u фиксирует, что локальная ветка main отслеживает удаленную ветку main, поэтому в дальнейшем будет достаточно просто выполнить git push. git clone <url> — это обратная операция для новой машины: она копирует весь репозиторий вместе с историей и автоматически настраивает origin. Удаленный репозиторий по HTTPS также работает; он использует тот же протокол, что и любая веб-страница, что помогает в сетях, где заблокирован исходящий порт 22. Если это утверждение требует пояснений, из чего на самом деле состоит HTTP-запрос описывает механику процесса.
Pull requests, issues и forks: компоненты GitHub, а не Git
Всё, что описано выше, относится к Git и работает с любым сервером. Три термина ниже — это функции GitHub. Другие хостинги копируют их, но сам Git о них ничего не знает.
Pull request (PR) — это запрос на слияние одной ветки с другой, оформленный в виде страницы для обсуждения. Вы отправляете add-backup, открываете PR в main, и сайт показывает разницу коммит за коммитом. Участники могут оставлять комментарии к отдельным строкам. Автоматизированные проверки сообщают о прохождении или ошибках для данной ветки. После нажатия кнопки слияния GitHub выполняет его в своей копии, а затем обновляет main. Название происходит от классического рабочего процесса, в котором вы просили мейнтейнера забрать (pull) вашу ветку в его репозиторий.
Issue — это нумерованная ветка обсуждения для отслеживания ошибок или задач. Она хранится в базе данных GitHub, а не в вашем репозитории. Это важно учитывать при выборе хостинга: если вы клонируете репозиторий, вы получите все коммиты, но ни одного issue. Чтобы выгрузить issues, необходимо использовать API.
Fork — это ваша собственная серверная копия чужого репозитория. У вас есть права на запись в эту копию, вы отправляете в неё ветку и открываете pull request из своей копии в исходную. Именно так вы вносите вклад в проект, авторы которого с вами не знакомы. Fork — это клон, который существует на GitHub и «помнит» свой источник.
Программное обеспечение работает со всеми тремя сущностями через тот же API, что и человек. Агент для проверки pull request, который вы запускаете на собственном сервере, отслеживает новые PR, читает diff и публикует комментарии к строкам кода. Такие соглашения, как файл AGENTS.md в корне репозитория, существуют потому, что теперь репозиторий читают не только люди, но и инструменты автоматизации.
Что на самом деле дает GitHub владельцу VPS
Начните с выноса данных за пределы сервера. Ваши скрипты развертывания и плейбуки должны храниться там, где они не зависят от настраиваемого ими сервера. Пересоберите VPS из чистого образа, клонируйте репозиторий и запустите скрипты. Сделайте репозиторий приватным и предоставьте серверу deploy key: SSH-ключ, привязанный только к одному репозиторию, а не ко всей учетной записи, и настроенный на доступ только для чтения. Утечка ключа с правами только на чтение скомпрометирует один репозиторий. Утечка ключа от учетной записи скомпрометирует всё, куда вы можете вносить изменения.
sudo git clone git@github.com:yourname/vps-deploy.git /srv/vps-deploy
cd /srv/vps-deploy
git pull --ff-only--ff-only запрещает создание merge commit. На сервере, который только потребляет изменения, слияние всегда является ошибкой, поэтому этот флаг превращает запутанную историю в простую ошибку fatal: Not possible to fast-forward, aborting.. На сервере произошло изменение, которого быть не должно. Найдите его перед тем, как снова выполнять pull.
Если вы клонируете репозиторий от имени root, а затем запускаете Git от другого пользователя, вы получите fatal: detected dubious ownership in repository at '/srv/vps-deploy'. Git отказывается читать репозиторий, владельцем которого является другой пользователь, так как враждебный .git/config может заставить Git выполнить произвольные команды. Исправьте владельца с помощью chown вместо добавления исключения safe.directory, так как исключение лишь подавляет проверку, не устраняя причину.
GitHub Actions: конвейеры сборки и развёртывания
Actions — это система CI/CD (непрерывной интеграции и непрерывной доставки) от GitHub. Добавьте YAML-файл в .github/workflows/, и GitHub запустит его при наступлении указанного вами события.
name: check
on:
push:
branches: [main]
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- run: sudo apt-get update && sudo apt-get install -y shellcheck
- run: shellcheck *.shЭтот файл является workflow (рабочим процессом). Job (задача) выполняется на одной машине. Step (шаг) — это одна команда или опубликованное действие. uses: подтягивает действие из другого репозитория, а @v7 фиксирует его мажорную версию (v7 является актуальной для actions/checkout по состоянию на август 2026 года). Всегда фиксируйте версии, так как нефиксированное действие означает, что код, который вы не читали, выполняется с доступом к вашим секретам.
runs-on: ubuntu-latest запрашивает у GitHub новую виртуальную машину, которая удаляется после завершения задачи. Стандартные раннеры бесплатны для публичных репозиториев, а бесплатный тариф включает 2000 минут в месяц для приватных репозиториев по состоянию на август 2026 года. Проверяйте актуальную страницу с ценами перед планированием бюджета на основе этой цифры.
Секреты хранятся в настройках репозитория и считываются как ${{ secrets.DEPLOY_KEY }}. Рабочий процесс, запущенный через pull request из форка, получает токен только для чтения и не имеет доступа к этим секретам, иначе посторонний мог бы открыть PR, единственной задачей которого было бы их вывести.
Запуск Actions runner на собственном VPS
runs-on: self-hosted отправляет задание на машину, которой вы владеете. На странице настроек runner в репозитории вы найдете команду для загрузки, адрес репозитория и токен регистрации, действующий один час. Вставьте последние два значения в REPO_URL и RUNNER_TOKEN, после чего настройка сведется к трем командам.
./config.sh --url "$REPO_URL" --token "$RUNNER_TOKEN"
sudo ./svc.sh install
sudo ./svc.sh start
./svc.sh statussvc.sh status должен показать, что служба активна, и вывести последние строки лога. Runner открывает исходящее HTTPS-соединение к GitHub и запрашивает работу, поэтому открывать входящие порты не требуется. svc.sh install создает systemd-юнит, и это тот шаг, который часто пропускают: без него runner завершается вместе с вашей SSH-сессией, а все последующие задания остаются в очереди без объяснения причин. полное руководство по настройке self-hosted runner на VPS содержит инструкции по обеспечению безопасности и очистке, которые необходимы для постоянно работающего runner.
Преимущество заключается в том, что для развертывания больше не нужен SSH-ключ, доступный из интернета, так как задание уже выполняется на целевой машине. Кэш сборки сохраняется между запусками, а лимит минут не расходуется.
Важное предупреждение: документация GitHub рекомендует использовать self-hosted runner только для приватных репозиториев. Форки публичного репозитория могут запустить вредоносный код на вашем runner, открыв pull request. Runner выполняет любые инструкции, указанные в файле workflow в этой ветке. В приватном репозитории, где вы контролируете права на push, риск невелик. В публичном репозитории считайте любой self-hosted runner машиной, на которой посторонние могут исполнять свой код.
Нужен ли вам вообще GitHub?
Нет. Git — это стандарт, а GitHub — лишь удобство. Forgejo и Gitea представляют собой self-hosted платформы для разработки (forge), которые объединяют хостинг Git-репозиториев с системой отслеживания задач и pull requests. Оба продукта поставляются в виде одного бинарного файла на Go и работают на небольшом VPS. Forgejo — это форк Gitea от 2022 года, на котором сейчас работает Codeberg. Перенос репозитория выполняется одной командой, так как протокол передачи данных идентичен.
git remote -v
git remote set-url origin git@git.example.com:you/vps-deploy.git
git push origin mainКаждый коммит переносится без потерь, поскольку любой клон уже содержит полную историю изменений. Что не переносится, так это надстройки, созданные GitHub: обсуждения в issues и pull requests. CI также не переносится автоматически. У Forgejo есть собственная реализация Actions, которая считывает похожий YAML из .forgejo/workflows/. В документации прямо указаны ограничения: GitHub Actions и Forgejo Actions — это не одно и то же, поэтому некоторые вещи могут не заработать сразу. Также потребуется настройка собственного runner. Планируйте этот этап как перенос (port), а не как простое копирование.
Честная причина, по которой большинство проектов остаются на GitHub, — это контрибьюторы. Публичный код должен находиться там, где у людей уже есть аккаунты. Ваши приватные скрипты развертывания — нет. Это два разных решения, и вы имеете право принимать их по-разному.
Что ломается в первую очередь и о чем говорит ошибка
Push отклонен. Вы видите следующее:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'github.com:yourname/vps-deploy.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.Кто-то выполнил push после вашего последнего pull, часто это правка, сделанная через веб-редактор. Выполните git pull --rebase, чтобы наложить ваши коммиты поверх чужих, а затем снова выполните push. Избегайте git push --force в общей ветке, так как это удалит чужие коммиты из этой ветки на сервере.
fatal: refusing to merge unrelated histories. Вы выполнили git init локально и позволили GitHub создать репозиторий с файлом README. У этих двух историй нет общих коммитов, поэтому Git не сможет угадать, как их объединить. Самый чистый способ исправления — клонировать копию с GitHub в новую папку и переместить туда ваши файлы.
error: src refspec main does not match any. Указанная вами ветка здесь отсутствует. Обычно в репозитории пока нет ни одного коммита или ваша ветка называется master. git branch --show-current решает эту проблему.
Секретный ключ попал в коммит. Немедленно смените учетные данные. Считайте их скомпрометированными с момента выполнения push, так как форки, зеркала и кэшированные копии содержат данные, которые вы не сможете удалить.
FAQ
Являются ли GitHub и Git одним и тем же?
Нет. Git — это программа для контроля версий, которую вы устанавливаете на компьютер; она работает без сети и без учетной записи. GitHub — это коммерческий хостинг-сервис, который хранит репозитории Git и добавляет к ним веб-интерфейс, систему отслеживания задач (issues), pull requests и CI. Git был выпущен в 2005 году, а GitHub запущен в 2008 году на его основе. Вы можете использовать Git бесконечно долго без GitHub. Любая функция GitHub опирается на Git как на фундамент.
Нужна ли мне учетная запись GitHub для использования Git на моем VPS?
Нет. git init, git commit и git log работают на сервере без настроенных удаленных репозиториев, чего уже достаточно для отслеживания изменений в /etc файлах или развертывания скриптов. Учетная запись становится полезной, когда вам нужна копия истории, которая сохранится в случае выхода сервера из строя, или если вы хотите клонировать репозиторий на вторую машину. Self-hosted решения, такие как Forgejo и Gitea, закрывают ту же потребность на вашем собственном оборудовании, а обычный SSH-ремоут, указывающий на bare-репозиторий на другом сервере, работает вообще без какого-либо стороннего ПО.
Что такое pull request?
Pull request — это запрос на слияние одной ветки с другой, дополненный страницей для обсуждения. Вы отправляете ветку (push), открываете PR в main, и хостинг отображает изменения коммит за коммитом, чтобы рецензенты могли оставлять комментарии к отдельным строкам, а автоматизированные проверки могли сообщать о результатах. Это функция GitHub, а не Git, поэтому в самом Git нет соответствующей команды. Другие хостинги реализуют ту же идею, иногда называя её merge request.
Стоит ли запускать GitHub Actions runner на своем VPS?
Для приватного репозитория — часто да. Задание выполняется на оборудовании, за которое вы уже платите, минуты не тарифицируются, кэш сборки остается актуальным, а для развертывания больше не нужно открывать входящий SSH-порт в интернет, так как runner сам подключается к GitHub и запрашивает задачи. Для публичного репозитория GitHub не рекомендует это делать: любой может сделать форк вашего репозитория и открыть pull request, чей workflow выполнит код на вашей машине.
Могу ли я позже перенести свои репозитории с GitHub?
Код — да, легко. Каждый клон содержит полную историю, поэтому git remote set-url origin <new url> с последующим push переносит всё, что содержит коммит. Что остается позади, так это слой, принадлежащий GitHub: issues, обсуждения pull request и история Actions живут в их базе данных, а не в вашей .git папке. Инструменты миграции могут скопировать задачи через API, а файлы workflow обычно требуют адаптации под CI нового хостинга. Понимание этого факта — главный аргумент в пользу того, чтобы хранить важную документацию внутри репозитория, а не в ветках обсуждения задач.