
Существует прекрасная общепринятая схема работы с контролем версий — у каждого разработчика своя копия проекта, коммиты в ветки, мерж, test‑сервер, pre‑prod, CI/CD.
Для больших проектов все отлично и автоматизировано. Нет никаких сомнений что так и должно быть, НО...
Есть мелкие проекты — какой‑нибудь сайт, где раз в пару месяцев надо внести небольшие правки и заказчик при этом каждый раз нанимает разных фрилансеров.
Естественно невозможно заставить фрилансера ради задачи на 2 часа поднимать у себя копию проекта и настраивать окружение (особенно если сайт не простой, например идет с коробочной CRM, гигантской БД и еще пачкой инфраструктурных решений в придачу).
И даже сделать фрилансеру отдельную копию проекта на сервере, а потом чистить ее, или следить за актуальностью ради мелкой задачи не имеет смысла.
Единственный вариант — это дать фрилансеру доступ к общей тестовой копии проекта на которой уже параллельно может работать другой фрилансер над другой 2х часовой задачей.
Организовать работу так чтобы они не пересекались в коде и не правили файлы друг друга — это можно сделать плюс‑минус вручную. Но дальше встает вопрос — как работать с контролем версий?
Поясню — фрилансер работает в IDE, но заливает измененные файлы сразу на тестовый сервер потому что ему нужно видеть прогресс в реальном времени «внес правку — посмотрел что вышло, внес дальше».
И вот он закончил задачу. Пришло время сделать коммит. Есть 2 пути:
1. Он может зайти на тестовый сервер по ssh и сделать коммит из консоли добавив только те файлы которые он менял (потому что с сервером работают параллельно другие и общее кол‑во незакомиченных измененных файлов больше).
Но если файлов много, то это довольно неудобно — надо вспоминать что именно ты менял и еще не ошибиться чтобы не закоммитить чужой скрипт.
2. Поэтому удобно сделать коммит с локалки из IDE. Там уже автоматом собираются только те файлы которые менял ты. Возникает вопрос что делать с тестовым сервером?
Можно было бы оставить его вообще без гита, но тут есть неудобства
— хотелось бы видеть в каких файлах продолжается работа и самое главное в чем именно тестовый отличается от гита (боевого)
— встречаются еще более странные случаи когда правку в какие‑нибудь «параметры компонента» или конфиг может внести вообще даже не программист а кто‑то типа админа сразу на сервере без IDE и тогда ему хорошо бы сделать коммит сразу из консоли сервера (хоть так).
И тут мы приходим к ситуации при которой у нас есть
— гит на тестовом сервере
— коммит в гите в удаленном репозитории (сделанный с локалки)
— измененные скрипты залитые напрямую на сервер (которые соответствуют коммиту)
— измененные скрипты по другим задачам в работе которые пока не надо коммитить
И очень хочется сделать git pull, но git, зараза, ругается что файлы на сервере изменены. Git сравнивает содержимое файла с тем, что записано в индексе и не понимает что измененные на сервере файлы на самом деле идентичны коммиту из удаленного репозитория.

Приходится откатывать все файлы которые есть в коммите и потом делать git pull. Это требует пачки ручных манипуляций (собрать список файлов для отката и так далее) и осложняется дополнительными кейсами когда например файла вообще не было ранее и в последнем коммите в гите он только добавился. Тогда откат (git checkout) не сработает и надо такие файлы удалять перед коммитом.
А еще хорошо бы сразу увидеть нет ли случайно локальных коммитов на сервере не выгруженных в удаленный репозиторий или еще подобной ерунды.
В итоге мы придумали решение — сделать bash скрипт «gitPullForce.sh» который собственно
— определяет какие файлы в невыгруженных коммитах удаленного репозитория отличаются от файлов на сервере.
— сделает checkout тем которым нужен checkout, удалит те которые нужно удалить, заодно проверит нет ли прочих расхождений между сервером и удаленным репозиторием (кол‑во невыгруженных коммитов их даты и все что может вызвать подозрение на дополнительные сложности)
— и в конце собственно сделает git pull чтобы все файлы из последних коммитов удаленного репозитория привелись в соответствие с ним но ПРИ ЭТОМ чтобы другие измененные файлы на сервере которые пока что незакомиченны остались нетронутыми.
Схема работы получается простой — закончил задачу на сервере, сделал коммит с локалки, вызывал одну команду на сервере и у тебя прошел корректный git pull именно по твоей задаче.

? Скрипт
После загрузки на сервер выставляем ему права на выполнение:
chmod +x gitForcePull.sh
Вызываем скрипт из категории где у вас инициализирован git (сам скрипт может располагаться в другом месте).
Можно сначала вызвать его с параметром -check чтобы он просто сообщил что собирается делать.

Вопрос: сталкиваетесь ли вы с такой проблемой? (счастливчиков которые стабильно работают на одном проекте без постоянного жонглирования случайными фрилансерами прошу не кидать помидоры. Просто радуйтесь что у все хорошо :))
Комментарии (16)

gybson_63
17.06.2026 20:12На данный момент это самый странный способ использования гита, который я видел. Гит при температуре сорок.

agorshkov23
17.06.2026 20:12Пусть фрилансеры по мере готовности вмерживают свои коммиты из своих веток в ветку test и она автоматически раскатывается на тестовом окружении.
Таким образом появится контроль кто и что сделал или кто всё сломал.

om-sv Автор
17.06.2026 20:12Так а на каком сервере они будут работать? Когда ты закончил задачу - тогда конечно, вмержил ветки, они раскатались и т.д. но пока ты в процессе выполнения задачи тебе же надо свой код запускать - фрилансеры это делают сразу на тестовом окружении напрямую и как раз это и создает проблемы. Если на тестовом окружении уже файлы вручную правились то ничего там автоматически не раскатается :)
А уж тем более такое понятие как "свои ветки" сразу требует однозначно иметь свой личный dev-сервер. Если бы он был у фрилансера то и проблем бы не было никаких.

agorshkov23
17.06.2026 20:12Фрилансеры могут одновременно тестировать свои наработки на тестовом стенде?

om-sv Автор
17.06.2026 20:12Ага, они так и делают. Самое главное - это распределить задачи чтобы они не пересекались "ты пилишь новый виджет в карточке товара, а ты иди поправь скрипт обмена с 1С". А учитывая что на проекте есть несколько сайтов + CRM система коробочная то там могут и 5 человек параллельно работать над разными задачами не пересекаясь. А развернуть хотя бы одну лишнюю/новую копию этого монстра может целый день уйти.

ZenyaSan
17.06.2026 20:12Очень похожая ситуация! Часто приходится: срочно и многократно делать мелкие правки или проверять экспериментальные функции прямо на сервере. И когда всё устаканивается, хочется синхронизировать через git pull, ан нет. Не даёт, потому что на сервере были ручные правки. В таких случаях действительно не хватает опции "Сделать пулл принудительно". Приходится возиться руками (часто выручает git stash).
В качестве оправдания - я единственный разработчик системы :)

yursergeev
17.06.2026 20:12Да, такая проблема встречается в маленьких проектах и при работе с разными фрилансерами. Она возникает из-за того, что сервер одновременно используется, как рабочее место и как место для деплоя. В итоге там появляются ручные правки, незакоммиченные изменения и код из Git, и всё это начинает конфликтовать при
git pull. Ваш скрипт в этом случае нормальное практическое решение. Он просто автоматизирует ручные шаги, которые иначе приходится делать каждый раз. Но по сути это не проблема Git, а проблема организации процесса. В более правильной схеме код не правят на сервере, а изменения попадают туда только через деплой из репозитория. Тогда никаких конфликтов при pull просто не возникает.

digrobot
17.06.2026 20:12git stash && git pull && git stash pop ?

om-sv Автор
17.06.2026 20:12[root@test2 test]# git stash && git pull && git stash pop
(.....)
error: The following untracked working tree files would be overwritten by merge: gradlew
Please move or remove them before you can merge.
Aborting

digrobot
17.06.2026 20:12А, я не учел, что еще и новые файлы создаются.
Корень проблемы в том, что изменения вносятся сразу в двух местах, и эти изменения надо как-то синхронизировать, а они могут различаться (и однажды не совпадут).
Я бы изменения на стейдже просто сбрасывал раз в сутки, и подтягивал dev ветку. Кто не успел закоммитить свою фичу, тот опоздал.

cmyser
17.06.2026 20:12git reset --hard origin master && git pull
Сбрасываем изменения на сервере, потом пулим.
Вообще делать изменения на сервере очень и очень плохая практика, настройте автоматический деплой из гитхаба/гитлаба, это не так сложно

om-sv Автор
17.06.2026 20:12git reset сбросит все изменения на сервере. А там есть изменения которые еще не закомичены и которые не надо сбрасывать. В других скриптах над которыми еще ведутся работы.
Да, я полностью согласен с вами что это плохая практика о чем и написал в самом начале статьи. Чтобы иметь автоматический деплой нужно иметь где-то рабочую копию проекта на которой непосредственно будет работать разработчик (в идеале на локалке у самого разработчика) а тут такой нет (почему ее нет и в чем проблема ее сделать описал в статье)

cmyser
17.06.2026 20:12закомитьте, пушните, и больше никогда не правьте код на сервере
И никому не позволяйте заходить на сервер и править там,
раскатите stage окружение, не плодите проблем
Ну правда, не просто так это придумано, дебажить больно такое
anonymous