web-dev-qa-db-fra.com

Comment puis-je forcer "git pull" pour écraser les fichiers locaux?

Comment forcer un écrasement de fichiers locaux sur un git pull?

Le scénario est le suivant:

  • Un membre de l'équipe modifie les modèles d'un site Web sur lequel nous travaillons.
  • Ils ajoutent des images au répertoire images (mais oublient de les ajouter sous contrôle de code source)
  • Ils envoient les images par courrier, plus tard, à moi
  • J'ajoute les images sous le contrôle de code source et les envoie à GitHub avec d'autres modifications
  • Ils ne peuvent pas extraire les mises à jour de GitHub car Git ne veut pas écraser leurs fichiers.

C'est l'erreur que j'obtiens:

erreur: le fichier d'arbre de travail non suivi 'public/images/icon.gif' serait écrasé par la fusion

Comment puis-je forcer Git à les écraser? La personne est un concepteur. En règle générale, je résous tous les conflits à la main. Le serveur dispose donc de la version la plus récente dont ils ont juste besoin pour mettre à jour leur ordinateur.

5771
Jakub Troszok

Important: Si vous apportez des modifications locales, elles seront perdues. Avec ou sans l'option --hard, tous les commits locaux qui n'ont pas été poussés seront perdus.[*]

Si vous avez des fichiers qui sont non suivis par Git (par exemple, le contenu utilisateur téléchargé), ces fichiers ne seront pas affectés.


Je pense que c'est la bonne façon:

git fetch --all

Ensuite, vous avez deux options:

git reset --hard Origin/master

OU Si vous êtes sur une autre branche:

git reset --hard Origin/<branch_name>

Explication:

git fetch télécharge le dernier depuis la télécommande sans essayer de fusionner ou de rebaser quoi que ce soit.

Ensuite, le git reset réinitialise la branche principale à ce que vous venez de récupérer. L'option --hard modifie tous les fichiers de votre arbre de travail afin qu'ils correspondent aux fichiers de Origin/master


Maintenir les commits locaux actuels

[*]: Il est intéressant de noter qu’il est possible de maintenir les commits locaux actuels en créant une branche à partir de master avant de réinitialiser:

git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard Origin/master

Après cela, tous les anciens commits seront conservés dans new-branch-to-save-current-commits

Changements non validés

Les modifications non engagées, cependant (même programmées), seront perdues. Assurez-vous de cacher et de commettre tout ce dont vous avez besoin. Pour cela, vous pouvez exécuter les tâches suivantes:

git stash

Et ensuite, pour réappliquer ces modifications non validées:

git stash pop
8139
RNA

Essaye ça:

git reset --hard HEAD
git pull

Il faut faire ce que tu veux.

808
Travis Reeder

AVERTISSEMENT: git clean supprime tous vos fichiers/répertoires non suivis et ne peut pas être annulé.


Parfois, seul clean -f n'aide pas. Si vous avez des répertoires non suivis, l'option -d est également requise:

# WARNING: this can't be undone!

git reset --hard HEAD
git clean -f -d
git pull

AVERTISSEMENT: git clean supprime tous vos fichiers/répertoires non suivis et ne peut pas être annulé.

Pensez à utiliser le drapeau -n (--dry-run) en premier. Cela vous montrera ce qui sera supprimé sans rien supprimer:

git clean -n -f -d

Exemple de sortie:

Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...
409

Comme Hérisson, je pense que les réponses sont terribles. Mais bien que la réponse de Hedgehog soit peut-être meilleure, je ne pense pas qu'elle soit aussi élégante qu'elle pourrait l'être. Pour ce faire, j'ai utilisé "fetch" et "fusion" avec une stratégie définie. Ce qui devrait faire en sorte que vos modifications locales soient préservées tant qu'elles ne font pas partie des fichiers avec lesquels vous essayez de forcer un remplacement. 

Commencez par valider vos modifications

 git add *
 git commit -a -m "local file server commit message"

Puis récupérer les modifications et écraser en cas de conflit

 git fetch Origin master
 git merge -s recursive -X theirs Origin/master

"-X" est un nom d'option et "leur" est la valeur de cette option. Vous choisissez d'utiliser "leurs" modifications au lieu de "vos" modifications en cas de conflit.

347
Richard Kersey

Au lieu de faire:

git fetch --all
git reset --hard Origin/master

Je conseillerais de faire ce qui suit:

git fetch Origin master
git reset --hard Origin/master

Pas besoin d'aller chercher toutes les télécommandes et les branches si vous allez réinitialiser à l'origine/branche principale non?

251
Johanneke

Il semble que le meilleur moyen consiste à faire d'abord:

git clean

Pour supprimer tous les fichiers non suivis, puis continuez avec le git pull...

125
Jakub Troszok

Attention, ceci effacera définitivement vos fichiers si vous avez des entrées directory/* dans votre fichier gitignore.

Certaines réponses semblent être terribles. Terrible dans le sens de ce qui est arrivé à @Lauri en suivant la suggestion de David Avsajanishvili.

Plutôt (git> v1.7.6):

git stash --include-untracked
git pull

Plus tard, vous pourrez nettoyer l'historique des cachettes.

Manuellement, un par un:

$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...

$ git stash drop stash@{0}
$ git stash drop stash@{1}

Brutalement, tout à la fois:

$ git stash clear

Bien sûr, si vous voulez revenir à ce que vous avez caché:

$ git stash list
...
$ git stash apply stash@{5}
102
Hedgehog

Vous pouvez trouver cette commande utile pour éliminer les modifications locales:

git checkout <your-branch> -f

Et puis faites un nettoyage (supprime les fichiers non suivis de l’arbre de travail):

git clean -f

Si vous souhaitez supprimer des répertoires non suivis en plus des fichiers non suivis:

git clean -fd
88
Vishal

Au lieu de fusionner avec git pull, essayez ceci: 

git fetch --all

suivi par:

git reset --hard Origin/master.

82
Lloyd Moore

La seule chose qui a fonctionné pour moi a été:

git reset --hard HEAD~5

Cela vous ramènera cinq commits et ensuite avec

git pull

J'ai trouvé qu'en regardant comment annuler une fusion Git .

55
Chris BIllante

Le problème de toutes ces solutions est qu’elles sont toutes trop complexes ou, bien plus, qu’elles suppriment tous les fichiers non suivis du serveur Web, ce que nous ne souhaitons pas, car nous avons toujours besoin des fichiers de configuration qui sont stockés. le serveur et non dans le référentiel Git.

Voici la solution la plus propre que nous utilisons:

# Fetch the newest code
git fetch

# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    rm -f -- "$file"
done

# Checkout all files which were locally modified
for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`
do
    git checkout -- "$file"
done

# Finally pull all the changes
# (you could merge as well e.g. 'merge Origin/master')
git pull
  • La première commande récupère les données les plus récentes.

  • La deuxième commande vérifie si des fichiers sont ajoutés au référentiel et supprime les fichiers non suivis du référentiel local, ce qui provoquerait des conflits.

  • La troisième commande extrait tous les fichiers modifiés localement.

  • Enfin, nous faisons un pull pour mettre à jour vers la version la plus récente, mais cette fois sans aucun conflit, car les fichiers non suivis qui sont dans le référentiel n’existent plus et tous les fichiers localement modifiés sont déjà les mêmes que dans le référentiel.

51

Tout d’abord, essayez la méthode standard:

git reset HEAD --hard # To remove all not committed changes!
git clean -fd         # To remove all untracked (non-git) files and folders!

Avertissement: Les commandes ci-dessus peuvent entraîner la perte de données/fichiers uniquement si vous ne les avez pas validées! Si vous n'êtes pas sûr, faites d'abord la sauvegarde de l'intégralité de votre dossier de référentiel.

Puis tirez à nouveau.

Si ci-dessus ne vous aide pas et que vous ne vous souciez pas de vos fichiers/répertoires non suivis (effectuez la sauvegarde en premier lieu au cas où), essayez les étapes simples suivantes:

cd your_git_repo  # where 'your_git_repo' is your git repository folder
rm -rfv *         # WARNING: only run inside your git repository!
git pull          # pull the sources again

Cela va supprimer tous les fichiers git (excempt .git/dir, où vous avez tous les commits) et le tirer à nouveau.


Pourquoi git reset HEAD --hard pourrait échouer dans certains cas?

  1. Règles personnalisées dans .gitattributes file

    Avoir la règle eol=lf dans .gitattributes pourrait amener git à modifier certaines modifications de fichier en convertissant les fins de ligne CRLF en LF dans certains fichiers texte.

    Si c'est le cas, vous devez valider ces modifications CRLF/LF (en les examinant dans git status), ou essayez: git config core.autcrlf false de les ignorer temporairement.

  2. Incompatibilité du système de fichiers

    Lorsque vous utilisez un système de fichiers qui ne prend pas en charge les attributs d'autorisation. Par exemple, vous avez deux référentiels, un sous Linux/Mac (ext3/hfs+) et un autre sur le système de fichiers FAT32/NTFS.

    Comme vous le constatez, il existe deux types de systèmes de fichiers différents. Ainsi, celui qui ne prend pas en charge les autorisations Unix ne peut pas réinitialiser les autorisations de fichiers sur un système ne prenant pas en charge ce type d'autorisations. Par conséquent, --hard vous essayez, git détecte toujours des "modifications".

44
kenorb

J'ai eu le même problème. Personne ne m'a donné cette solution, mais cela a fonctionné pour moi.

Je l'ai résolu par:

  1. Supprimer tous les fichiers. Ne laissez que le répertoire .git.
  2. git reset --hard HEAD
  3. git pull
  4. git Push

Maintenant ça marche.

39
John John Pichler

J'avais un problème similaire. Je devais faire ceci:

git reset --hard HEAD
git clean -f
git pull
27
Ryan

J'ai résumé d'autres réponses. Vous pouvez exécuter git pull sans erreur:

git fetch --all
git reset --hard Origin/master
git reset --hard HEAD
git clean -f -d
git pull

Attention : Ce script est très puissant, vous risquez donc de perdre vos modifications.

27
Robert Moon

Sur la base de mes propres expériences similaires, la solution proposée par Strahinja Kustudic ci-dessus est de loin la meilleure. Comme d'autres l'ont fait remarquer, une simple réinitialisation matérielle supprime tous les fichiers non suivis, qui peuvent contenir de nombreuses choses que vous ne souhaitez pas supprimer, telles que les fichiers de configuration. Ce qui est plus sûr, c’est de ne supprimer que les fichiers sur le point d’être ajoutés. En outre, vous voudrez probablement également extraire les fichiers modifiés localement qui sont sur le point d’être mis à jour.

Dans cet esprit, j'ai mis à jour le script de Kustudic pour faire exactement cela. J'ai aussi corrigé une faute de frappe (un 'manquant dans l'original).

#/bin/sh

# Fetch the newest code
git fetch

# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    echo "Deleting untracked file $file..."
    rm -vf "$file"
done

# Checkout all files which have been locally modified
for file in `git diff HEAD..Origin/master --name-status | awk '/^M/ {print $2}'`
do
    echo "Checking out modified file $file..."
    git checkout $file
done

# Finally merge all the changes (you could use merge here as well)
git pull
26
Rolf Kaiser

Je crois qu'il existe deux causes possibles de conflit, qui doivent être résolues séparément, et pour autant que je sache, aucune des réponses ci-dessus ne traite des deux:

  • Les fichiers locaux non suivis doivent être supprimés, soit manuellement (plus sûr), soit comme suggéré dans d'autres réponses, par git clean -f -d

  • Les validations locales qui ne se trouvent pas sur la branche distante doivent également être supprimées. Le moyen le plus simple d'y parvenir est d'utiliser: git reset --hard Origin/master (remplacez 'maître' par la branche sur laquelle vous travaillez et exécutez d'abord un git fetch Origin)

23
tiho

Un moyen plus simple serait de:

git checkout --theirs /path/to/file.extension
git pull Origin master

Cela remplacera votre fichier local avec le fichier sur git

20
maximus 69

Il semble que la plupart des réponses ici se concentrent sur la branche master; Cependant, il arrive que je travaille sur la même branche dans deux endroits différents et que je souhaite qu'un rebase dans l'un se répercute sur l'autre sans trop de sauts.

Sur la base d'une combinaison de la réponse de l'ARN et de la réponse de torek à une question similaire , j'ai trouvé ceci qui fonctionne à merveille:

git fetch
git reset --hard @{u}

Exécutez ceci depuis une branche et cela ne réinitialisera votre branche locale que vers la version en amont.

Cela peut également être mis dans un alias de git (git forcepull):

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

Ou, dans votre fichier .gitconfig:

[alias]
  forcepull = "!git fetch ; git reset --hard @{u}"

Prendre plaisir!

20
JacobEvelyn

J'ai eu le même problème et pour une raison quelconque, même un git clean -f -d ne le ferait pas. Voici pourquoi: Pour une raison quelconque, si votre fichier est ignoré par Git (via une entrée .gitignore, je suppose), il est toujours dérangeant de remplacer cela par un pull , mais un clean ne sera pas supprimez-le, sauf si vous ajoutez -x.

19
Tierlieb

Je viens de résoudre ce problème moi-même par:

git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m 'tmp'
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp

où la dernière commande donne une liste de vos changements locaux. Continuez à modifier la branche "tmp" jusqu'à ce qu'elle soit acceptable, puis rejoignez Master avec: 

git checkout master && git merge tmp

Pour la prochaine fois, vous pouvez probablement gérer cela de manière plus propre en recherchant "branche git stash", bien que stash risque de vous causer des problèmes lors des premiers essais. Faites donc votre première expérience sur un projet non critique ...

18
Simon B.

J'ai une situation étrange que ni git clean ni git reset ne fonctionne. Je dois supprimer le fichier en conflit de git index en utilisant le script suivant sur chaque fichier non suivi:

git rm [file]

Ensuite, je peux bien tirer.

17
Chen Zhang

Je connais une méthode beaucoup plus facile et moins douloureuse:

$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

C'est tout!

16
ddmytrenko

Ces quatre commandes fonctionnent pour moi.

git reset --hard HEAD
git checkout Origin/master
git branch -D master
git checkout -b master

Pour vérifier/extraire après avoir exécuté ces commandes

git pull Origin master

J'ai essayé beaucoup mais j'ai finalement eu du succès avec ces commandes.

13
vishesh chandra

Il suffit de faire

git fetch Origin branchname
git checkout -f Origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge Origin/branchname

Ainsi, vous évitez tous les effets secondaires indésirables, comme la suppression de fichiers ou de répertoires que vous souhaitez conserver, etc.

12
user2696128

Malgré la question initiale, les réponses les plus fréquentes peuvent poser problème aux personnes confrontées au même problème mais ne voulant pas perdre leurs fichiers locaux. Par exemple, voir les commentaires de Al-Punk et crizCraig. 

La version suivante valide vos modifications locales dans une branche temporaire (tmp), extrait la branche d'origine (qui, je suppose, est master) et fusionne les mises à jour. Vous pouvez le faire avec stash, mais j’ai trouvé qu’il était généralement plus simple d’utiliser la méthode branche/fusion.

git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master

git fetch Origin master
git merge -s recursive -X theirs Origin master

où nous supposons que autre référentiel est Origin master.

12
Snowcrash

Réinitialisez l'index et la tête à Origin/master, mais ne réinitialisez pas l'arbre de travail:

git reset Origin/master
11
user811773

Exigences:

  1. Suivez les changements locaux pour que personne ici ne les perde jamais.
  2. Faites en sorte que le référentiel local corresponde au référentiel Origin distant.

Solution:

  1. Stash les changements locaux.
  2. Récupérer avec un nettoyer de fichiers et répertoires ignoring .gitignore et réinitialisation matérielle à Origine .

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard Origin/master
    
9
vezenkov

J'ai lu toutes les réponses mais je cherchais une seule commande pour le faire. Voici ce que j'ai fait. Ajout d'un alias de git à .gitconfig

[alias]
      fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"

Exécuter votre commande en tant que 

git fp Origin master

équivalent à

git fetch Origin master
git reset --hard Origin/master
9
Venkat Kotra

N'utilisez pas git reset --hard. Cela effacera leurs modifications qui pourraient bien être totalement indésirables. Au lieu:

git pull
git reset Origin/master
git checkout <file1> <file2> ...

Vous pouvez bien sûr utiliser git fetch au lieu de git pull puisqu'il ne va clairement pas fusionner, mais si vous tirez, il est logique de continuer à tirer ici.

Donc, ce qui se passe ici, c'est que git pull met à jour votre référence d'origine/maître ; git reset met à jour votre référence de branche locale on pour qu'elle soit identique à Origin/master sans mettre à jour aucun fichier, votre état d'extraction n'est donc pas modifié; alors git checkout rétablit les fichiers dans l'état d'index de votre branche locale selon les besoins. Dans les cas où exactement le même fichier a été ajouté sur le maître en direct et en amont, l'index correspond déjà au fichier après la réinitialisation. Ainsi, dans le cas habituel, vous n'avez pas besoin de faire git checkout du tout.

Si la branche en amont contient également des commits que vous souhaitez appliquer automatiquement, vous pouvez suivre une variation subtile du processus:

git pull
git merge <commit before problem commit>
git reset <problem commit>
git checkout <file1> <file2> ...
git pull
8
Jim Driscoll

C’est la meilleure pratique pour annuler des modifications:

  • git commit Validez vos modifications par étapes afin qu’elles soient sauvegardées dans le reflog (voir ci-dessous).
  • git fetch Récupère les dernières modifications en amont
  • git reset --hard Origin/master Réinitialisation matérielle à la branche maître d'origine

Le reflogbranches d’enregistrements et autres références en cours de mise à jour dans le référentiel local. Ou simplement - le reflog est le historique de vos modifications.

C'est donc toujours une bonne pratique de s'engager. Les commits sont ajoutés au refog, ce qui garantit que vous aurez toujours le moyen de récupérer le code supprimé.

7
Jordan Georgiev

J'ai utilisé cette commande pour supprimer les fichiers locaux m'empêchant d'effectuer une extraction/fusion. Mais fais attention! Exécutez d'abord git merge … pour voir s'il n'y a que les fichiers que vous voulez vraiment supprimer.

git merge Origin/master 2>&1 >/dev/null | grep ^[[:space:]] | sed s/^[[:space:]]//g | xargs -L1 rm
  • git merge liste entre autres tous ces fichiers. Ils sont précédés par des espaces blancs.
  • 2>&1 >/dev/null redirige la sortie d'erreur vers la sortie standard afin qu'elle soit récupérée par grep.
  • grep ^[[:space:]] ne filtre que les lignes portant des noms de fichier.
  • sed s/^[[:space:]]//g coupe l'espace blanc depuis le début.
  • xargs -L1 rm appelle rm sur chacun de ces fichiers, en les supprimant.

Manipuler avec précaution: Quel que soit le résultat de git merge, la rm sera appelée pour chaque ligne commençant par un espace.

5
Glutexo

J'essayais d'utiliser la branche Material2 sur Angular2-Webpack-Starter et j'ai passé un sacré bout de temps. C’est la seule façon pour moi de télécharger et d’utiliser cette branche.

git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git

cd angular2-webpack-starter/

git checkout -b material2

Ouvrez le dossier du projet et supprimez tous les fichiers et dossiers non cachés. Laissez tous les cachés.

git add .

git commit -m "pokemon go"

git reset --hard

git pull Origin material2

(Lorsque l'éditeur apparaît, appuyez sur ': wq', puis appuyez sur Enter)

Maintenant tu es prêt.

5
Helzgate

Sous Windows, effectuez cette commande unique:

git fetch --all & git reset --hard Origin/master
3
Luca C.

Vous pouvez ignorer ce fichier avec un fichier dans le dossier de base de votre projet:

.gitignore

public/images/*

Extrayez ensuite les modifications puis supprimez cette ligne de votre fichier gitignore.

3
Daniel Gaytán

git fetch --all && git reset --hard Origin/master && git pull

0
Suge

1: réinitialiser un commit précédent

git reset --hard HEAD

2: Supprimer les fichiers non suivis

git clean -f

3: tire les commits

git pull

Sources:

0
abhijithvijayan

Tu pourrais essayer

git pull --force

si vous voulez écraser tous les fichiers locaux

0
Ultan Kearns
git fetch --all

alors si vous êtes sur la branche principale

git reset --hard Origin/master

else

git reset --hard Origin/master<branch_name>
0
SUJITKUMAR SINGH

si vous souhaitez réinitialiser la branche de suivi à distance de manière générique, utilisez:

git fetch
git reset --keep Origin/$(git rev-parse --abbrev-ref HEAD)

si vous souhaitez également réinitialiser vos modifications locales:

git fetch
git reset --hard Origin/$(git rev-parse --abbrev-ref HEAD)
0
warch