Как заставить git pull перезаписывать все при каждом нажатии?

203

У меня есть центральное голое хранилище, в котором есть три репозитория для разработчиков, которые тянут и толкают к нему нормально.

У меня также есть два других репозитория, которые извлекают данные из чистого репозитория CENTRAL: один - это живой сервер, а другой - сервер тестирования / стадии - каждый из которых извлекает из своей соответствующей ветви.

Сценарий таков: у меня есть post-updateхук-скрипт в репозитории CENTRAL, который автоматически обращается к тестовым и живым репо и запускает команду pull для каждого из них. Это обновляет как тестовые, так и живые серверы, все в зависимости от того, какая ветвь имеет новые коммиты. Это все прекрасно работает.

Проблема заключается в следующем: в чрезвычайной ситуации могут возникать ситуации, когда файлы могут напрямую обновляться на сервере (через ftp или что-либо еще), и сценарий CENTRAL после обновления завершается сбоем, поскольку возникают конфликты слияния / перезаписи. Этого сценария избежать невозможно, и он неизбежен.

Я хотел бы, чтобы это произошло так: я хочу, чтобы при извлечении из живых и тестовых сайтов всегда перезаписывались / объединялись при извлечении. Всегда. Эти репозитории будут доступны только для извлечения, поскольку они не предназначены для разработки.

Во всех моих исследованиях я не могу найти хорошее решение, чтобы вытягивание всегда вызывало перезапись локальных файлов. Это вообще возможно? Это сделало бы отличный сценарий развития, если так.

bmilesp
источник
1
Хотя я голосовал за ответ «Сброс того, что вы только что получили» ниже, я думаю, что решение вашей реальной проблемы состоит в том, чтобы не вносить внеплановые изменения. Модификации, какими бы срочными они не были, всегда должны проходить контроль версий. Никто, кроме операторов, не должен иметь прямого доступа к работающим сайтам (например, не разработчики). Постоянное использование контроля версий означает, что у вас есть отчет о том, когда были внесены изменения и кто их сделал, и лучшие инструменты для работы с ними. Зачем это подрывать, без реальной выгоды?
Фил Миллер
1
@Novelocrat правильно, я понимаю, что вы говорите. К сожалению, существует ряд сценариев, когда кто-то может загрузить файл непосредственно на сервер. В этом случае мне нужно будет выполнить несколько команд для повторной синхронизации репозиториев. Ранее мы использовали сценарий FTP для перемещения файлов из репозитория на сервер. Предложенный выше метод просто устранит шаг FTP, который в прошлом работал очень хорошо.
bmilesp
3
Поэтому не позволяйте людям напрямую обращаться к серверу. Заблокируйте доступ по FTP и SSH или скажите им, что они будут уволены за внесение необъяснимых изменений. Продолжение такой практики только навредит вам и вашей команде в долгосрочной перспективе.
Фил Миллер

Ответы:

510

На самом деле идеальный способ сделать это - вообще не использовать pull, а вместо этого fetchи reset:

git fetch origin master
git reset --hard FETCH_HEAD
git clean -df

(Перейдя masterна любую ветку, которой вы хотите следовать.)

pullпредназначен для слияния изменений каким-то образом, тогда resetкак разработан для простого соответствия вашей локальной копии конкретному коммиту.

Вы можете рассмотреть несколько различные варианты в cleanзависимости от потребностей вашей системы.

янтарный
источник
3
@ user730569 reset --hard- это команда, которая используется для принудительного перевода состояния рабочего каталога (и текущей ветви) в состояние, соответствующее состоянию определенного коммита.
Янтарная
25
FETCH_HEADявляется ссылкой, которая автоматически создается fetchдля представления выбранной ссылки. Он не объединяется, просто перезаписывается всякий раз, когда вы делаете выборку. cleanэто команда, которая удаляет файлы, которые не отслеживаются git, -dfфлаги говорят ей удалить каталоги ( -d) и фактически выполнять удаление ( -f).
Янтарная
4
почему нет ключевого слова для этого? Мне это нужно гораздо чаще, чем тянуть.
Вольфганг Fahl
15
Возможно, вы захотите использовать git clean -dnперед использованием, git clean -dfчтобы увидеть, какие файлы / папки будут удалены. git clean -dfможет быть отменено, только если у вас есть резервная копия
Ибрагим Лаваль
1
@NickMiddleweek Я волновался git clean -df, удалят также gitignored файлы, но оказывается, что это не так. git clean --helpговорит: «Обычно удаляются только файлы, неизвестные Git, но если указана опция -x, игнорируемые файлы также удаляются. Это может, например, быть полезно для удаления всех продуктов сборки».
Nickang
6

Я не уверен, как сделать это в одной команде, но вы могли бы сделать что-то вроде:

git reset --hard
git pull

или даже

git stash
git pull
Мэтт Вулф
источник
Для того, чтобы работать в одной команде: git reset --hard && git pull. В качестве альтернативы, но не лучше git reset --hard; git pull. Использование &&будет запускать вторую команду только в том случае, если первая команда была успешной. ;будет запускать его независимо от кода выхода первой команды.
мазуньки
5

Чтобы вытащить копию ветви и принудительно перезаписать локальные файлы из источника, используйте:

git reset --hard origin/current_branch

Вся текущая работа будет потеряна, и она будет такой же, как и исходная ветка.

Эндрю Аткинсон
источник
5
git reset --hard HEAD
git fetch --all
git reset --hard origin/your_branch
Dzmitry
источник
2

Вы можете изменить крючок, чтобы вытереть все в чистоте.

# Danger! Wipes local data!

# Remove all local changes to tracked files
git reset --hard HEAD

# Remove all untracked files and directories
git clean -dfx

git pull ...
Дитрих Эпп
источник
2
что делает х? объясните пожалуйста переключатели
Стив К
2
Я думаю, что х должен удалить все неотслеживаемые файлы. Трудно сказать в manpage-говорить, поэтому у нас так.
JosephK
2
@JosephK: это неправильно. Основное назначение git clean- это «Удалить неотслеживаемые файлы из рабочего дерева» (вверху страницы). Обычно это не относится к игнорируемым файлам, но -xуказывает также git cleanна включение игнорируемых файлов (за исключением того, что это не влияет на файлы, игнорируемые -eпараметром).
Дитрих Эпп
2

Если вы еще не зафиксировали локальные изменения со времени последнего извлечения / клонирования, вы можете использовать:

git checkout *
git pull

checkoutочистит ваши локальные изменения с помощью последнего локального коммита и pullвнесет его в удаленный репозиторий

Maviles
источник