Як змусити git pull, щоб перезаписати все на кожному тягненні?


203

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

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

Сценарій такий: у мене на post-updateскрипті CENTRAL repo є гак-скрипт, який автоматично отримує доступ до тесту і репост в реальному часі і виконує команду pull на кожному. Це оновлює як тестові, так і живі сервери, все залежно від того, яка галузь має нові коміти. Це все чудово працює.

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

Що я хотів би, щоб це сталося, це таке: я хочу, щоб витяг з веб-сайтів в реальному і тестовому режимі завжди перезаписувався / зливався під час потягу. Завжди. Ці репости будуть лише тягучими, оскільки вони не для розвитку.

У всіх своїх дослідженнях я не можу знайти гарного рішення, щоб витяг завжди примушував перезаписати локальні файли. Це взагалі можливо? Якщо так, то це створить чудовий сценарій розвитку.


1
Хоча я голосував за "перезавантаження того, що ви щойно знайшли", відповідь нижче, я думаю, що рішення вашої реальної проблеми полягає в тому, щоб не вносити зміни поза межами діапазону. Модифікації, як би не були термінові, завжди повинні проходити контроль версій. Ніхто, крім операторів, не повинен мати прямий доступ до запущених сайтів (наприклад, не розробники). Використання керування версіями послідовно означає, що ви маєте запис про те, коли були внесені зміни та хто їх вніс, та кращі інструменти для роботи з ними. Навіщо її підривати без жодної реальної вигоди?
Філ Міллер

1
@ Правознавець, я розумію, що ви говорите. На жаль, існує низка сценаріїв, коли хтось може завантажити файл безпосередньо на сервер. У цьому випадку мені потрібно виконати ряд команд, щоб повторно синхронізувати репост. Раніше ми використовували 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
чому для цього немає ключового слова? Мені це потрібно набагато частіше, ніж тягнути.
Вольфганг Фал

14
Ви можете скористатися git clean -dnперед використанням, git clean -dfщоб побачити, які файли / папки буде видалено. git clean -dfможна змінити лише в тому випадку, якщо у вас була резервна копія
Ібрагім Логал

1
@NickMiddleweek Я хвилювався git clean -df, що видалити файли з погіршенням також буде, але виявляється, що це не буде. 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

Вся поточна робота буде втрачена, і вона буде такою ж, як і галузь походження



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
що робить x? поясніть, будь ласка, перемикачі
Стів К

2
Я вважаю, що x повинен видалити всі незафіксовані файли. Важко сказати в manpage-говорить, тому ми маємо ТАК.
JosephK

2
@JosephK: Це неправильно. Основна мета git cleanвже - "Видалити непотрібні файли з робочого дерева" (вгорі сторінки). Зазвичай це не включає проігноровані файли, але -xповідомляє git cleanтакож включати ігноровані файли (за винятком цього, це не впливає на файли, ігноровані -eопцією).
Дітріх Епп

2

Якщо ви ще не здійснили локальні зміни з моменту останнього потягу / клонування, ви можете використовувати:

git checkout *
git pull

checkoutочистить ваші локальні зміни з останньою локальною комісією та pullсинхронізує їх до віддаленого сховища

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.