Существует прекрасная общепринятая схема работы с контролем версий — у каждого разработчика своя копия проекта, коммиты в ветки, мерж, 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)


  1. anonymous
    17.06.2026 20:12


  1. gybson_63
    17.06.2026 20:12

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


  1. agorshkov23
    17.06.2026 20:12

    Пусть фрилансеры по мере готовности вмерживают свои коммиты из своих веток в ветку test и она автоматически раскатывается на тестовом окружении.

    Таким образом появится контроль кто и что сделал или кто всё сломал.


    1. om-sv Автор
      17.06.2026 20:12

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

      А уж тем более такое понятие как "свои ветки" сразу требует однозначно иметь свой личный dev-сервер. Если бы он был у фрилансера то и проблем бы не было никаких.


      1. agorshkov23
        17.06.2026 20:12

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


        1. om-sv Автор
          17.06.2026 20:12

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


  1. ZenyaSan
    17.06.2026 20:12

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

    В качестве оправдания - я единственный разработчик системы :)


  1. yursergeev
    17.06.2026 20:12

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


  1. digrobot
    17.06.2026 20:12

    git stash && git pull && git stash pop ?


    1. 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


      1. digrobot
        17.06.2026 20:12

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


  1. cmyser
    17.06.2026 20:12

    git reset --hard origin master && git pull

    Сбрасываем изменения на сервере, потом пулим.

    Вообще делать изменения на сервере очень и очень плохая практика, настройте автоматический деплой из гитхаба/гитлаба, это не так сложно


    1. om-sv Автор
      17.06.2026 20:12

      git reset сбросит все изменения на сервере. А там есть изменения которые еще не закомичены и которые не надо сбрасывать. В других скриптах над которыми еще ведутся работы.

      Да, я полностью согласен с вами что это плохая практика о чем и написал в самом начале статьи. Чтобы иметь автоматический деплой нужно иметь где-то рабочую копию проекта на которой непосредственно будет работать разработчик (в идеале на локалке у самого разработчика) а тут такой нет (почему ее нет и в чем проблема ее сделать описал в статье)


      1. cmyser
        17.06.2026 20:12

        закомитьте, пушните, и больше никогда не правьте код на сервере

        И никому не позволяйте заходить на сервер и править там,

        раскатите stage окружение, не плодите проблем

        Ну правда, не просто так это придумано, дебажить больно такое


  1. Kuch
    17.06.2026 20:12

    Статью не читал, но по комментариям хочу спросить.

    git pull --force --autostash

    Чем не выход?


    1. om-sv Автор
      17.06.2026 20:12

      Это будет примерно тоже что предлагали выше: git stash && git pull && git stash pop

      В случае если появились новые файлы эта команда спотыкается