Comment forcer git pull à tout écraser à chaque pull?

203

J'ai un référentiel nu CENTRAL qui a trois référentiels de développeurs tirant et poussant normalement.

J'ai également deux autres référentiels qui tirent du référentiel nu CENTRAL: l'un est le serveur en direct, et l'autre est un serveur de test / stage - chacun tirant de sa propre branche respective.

Le scénario est le suivant: j'ai un post-updatescript de hook sur le référentiel CENTRAL qui accède automatiquement aux repos de test et live et exécute une commande pull sur chacun. Cela met à jour les serveurs de test et les serveurs en direct, tous en fonction de la branche qui a de nouveaux commits. Tout cela fonctionne très bien.

Le problème est le suivant: il peut arriver en cas d'urgence que les fichiers soient directement mis à jour sur le serveur (via ftp ou autre) et le script de post-mise à jour CENTRAL échouera alors car des conflits de fusion / écrasement se produiront. Il n'y a aucun moyen d'éviter ce scénario, et c'est inévitable.

Ce que j'aimerais qu'il se passe, c'est ceci: je veux que le pull des sites en direct et de test écrase / fusionne toujours au pull. Toujours. Ces référentiels seront à extraction uniquement car ils ne sont pas destinés au développement.

Dans toutes mes recherches, je ne trouve pas de bonne solution pour qu'un pull force toujours un écrasement des fichiers locaux. Est-ce possible? Si tel était le cas, cela constituerait un excellent scénario de développement.

bmilesp
la source
1
Bien que j'ai voté pour la réponse «réinitialiser ce que vous venez de chercher» ci-dessous, je pense que la solution à votre vrai problème est de ne pas apporter de modifications hors bande. Les modifications, aussi urgentes soient-elles, doivent toujours passer par le contrôle de version. Personne, à l'exception des opérateurs, ne devrait avoir un accès direct aux sites en cours d'exécution (par exemple, pas aux développeurs). L'utilisation constante du contrôle de version signifie que vous disposez d'un enregistrement de la date à laquelle les modifications ont été apportées, de qui les a apportées et de meilleurs outils pour les utiliser. Pourquoi le renverser, sans réel avantage?
Phil Miller
1
@Novelocrat à droite, je comprends ce que vous dites. Malheureusement, il existe un certain nombre de scénarios où quelqu'un pourrait télécharger un fichier directement sur le serveur. Dans ce cas, je devrais exécuter un certain nombre de commandes pour resynchroniser le repos. Auparavant, nous utilisions un script FTP pour déplacer des fichiers du dépôt vers le serveur. La méthode proposée ci-dessus éliminerait simplement l'étape FTP, qui a très bien fonctionné dans le passé.
bmilesp
3
Alors, ne laissez pas les gens accéder directement au serveur. Verrouillez l'accès FTP et SSH, ou dites-leur qu'ils seront renvoyés pour avoir apporté des modifications non comptables. Laisser ce genre de pratique continuer ne fait que vous blesser, vous et votre équipe, à long terme.
Phil Miller

Réponses:

510

Vraiment, le moyen idéal de le faire est de ne pas utiliser pulldu tout, mais plutôt fetchet reset:

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

(Modification masterde la branche que vous souhaitez suivre.)

pullest conçu autour de la fusion des modifications d'une manière ou d'une autre, alors qu'il resetconsiste simplement à faire correspondre votre copie locale à un commit spécifique.

Vous pouvez envisager des options légèrement différentes cleanselon les besoins de votre système.

ambre
la source
3
@ user730569 reset --hardest une commande qui est utilisée pour forcer l'état du répertoire de travail (et de la branche courante) à un état correspondant à celui d'un commit particulier.
Amber
25
FETCH_HEADest une référence qui est automatiquement créée par fetchpour représenter la référence récupérée. Ce n'est pas fusionné, juste écrasé directement chaque fois que vous effectuez une extraction. cleanest une commande qui supprime les fichiers qui ne sont pas suivis par git, les -dfindicateurs lui indiquent de supprimer les répertoires ( -d) et de faire la suppression (-f ).
Amber
4
pourquoi n'y a-t-il pas de mot-clé pour cela? J'ai besoin de ça beaucoup plus souvent que de tirer.
Wolfgang Fahl
15
Vous voudrez peut-être utiliser git clean -dnavant d'utiliser git clean -dfafin de voir quels fichiers / dossiers seront supprimés. git clean -dfne peut être inversé que si vous aviez une sauvegarde
Ibrahim Lawal
1
@NickMiddleweek J'étais inquiet de git clean -dfsupprimer également les fichiers gitignored, mais il s'avère que non. git clean --helpindique "Normalement, seuls les fichiers inconnus de Git sont supprimés, mais si l'option -x est spécifiée, les fichiers ignorés sont également supprimés. Cela peut, par exemple, être utile pour supprimer tous les produits de génération."
nickang
6

Je ne sais pas comment le faire dans une seule commande mais vous pourriez faire quelque chose comme:

git reset --hard
git pull

ou même

git stash
git pull
Matt Wolfe
la source
Pour exécuter en une seule commande: git reset --hard && git pull. Sinon, mais pas mieux, git reset --hard; git pull. L'utilisation &&exécutera la deuxième commande uniquement si la première commande a réussi. ;l'exécutera quel que soit le code de sortie de la première commande.
mazunki
5

Pour extraire une copie de la branche et forcer l'écrasement des fichiers locaux depuis l'origine, utilisez:

git reset --hard origin/current_branch

Tout le travail en cours sera perdu et ce sera alors le même que la branche d'origine

Andrew Atkinson
la source
5
git reset --hard HEAD
git fetch --all
git reset --hard origin/your_branch
Dzmitry
la source
2

Vous pouvez changer le crochet pour tout nettoyer.

# 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 ...
Dietrich Epp
la source
2
que fait x? veuillez expliquer les commutateurs
Steve K
2
Le x est censé supprimer tous les fichiers non suivis, je pense. Difficile à dire dans les pages de manuel, c'est pourquoi nous avons SO.
JosephK
2
@JosephK: C'est incorrect. L'objectif de base de git cleanest déjà "Supprimer les fichiers non suivis de l'arborescence de travail" (haut de la page). Normalement, cela n'inclut pas les fichiers ignorés, mais -xindique git cleand'inclure également les fichiers ignorés (sauf que cela n'affecte pas les fichiers ignorés par l' -eoption).
Dietrich Epp
2

Si vous n'avez pas encore validé les modifications locales depuis le dernier pull / clone, vous pouvez utiliser:

git checkout *
git pull

checkouteffacera vos modifications locales avec le dernier commit local et pullle synchronisera vers le référentiel distant

Maviles
la source