LE bazar des sauts de ligne avec GIT

Le problème exposé dans ce sujet a été résolu.

Bonjour zesteux,

Je code un site web en php sous windows avec WAMP. J'ai fait en sorte avec un script bash pour que quand je push sur master, le répertoire www du site est automatiquement pull. J'ai aussi un serveur de test qui se met à jour avec le même script mais quand une branche commençant par dev- est push. A la base ça fonctionne nickel. Par contre je me heurte au problème des sauts de ligne pas compatibles entre windows et linux, et c'est un problème récurrent que je n'arrive pas à résoudre définitivement.

D'après certains conseils trouvés sur le web, j'ai réglé le paramètre core.autocrlf à true sous windows et à input sous linux. Mais le problème persiste. J'ai aussi essayé de créer un fichier .gitattributesmais ça n'a pas non plus aidé.

A l'origine, mon repos GIT a été importé de SVN et converti automatiquement par GIT. A l'époque où j'étais sur SVN je n'avais pas ce problème, les update ne plantaient jamais.

Le scénario est le suivant:

  1. JE fais des modifs dans truc.php sous windows
  2. Je commit, puis push
  3. Lors du push, le script côté serveur s'exécute et tente un pull
  4. LE pull plante avec un message similaire à celui-ci:
1
2
3
4
Aborting
The folowing files would be overwritten by merge :  
truc.php  
Please, commit or stage your changes before you can merge  

A ce stade, j'ai beau essayer tout ce que je veux sur le serveur, je n'arrive pas à pull. LE même message d'erreur revient toujours en indiquant toujours les mêms fichiers, fichiers que je n'ai évidemment jamais modifié sur le serveur. J'ai déjà essayé toutes ces commandes sans résultat :

  • stash puis pull de nouveau, comme conseillé dans le message d'erreur. JE n'ai toujours pas compris comment on utilisait cette commande stash et à quoi elle servait mais c'est un autre sujet.
  • reset –hard
  • reset –ahrd puis checkout, ou même checkout sur une autre branche juste pour le fun avant de revenir, auquel cas il refuse le checkout
  • fetch puis checkout séparément, auquel cas il refuse le checkout
  • ftech puis merge et idem

Complètement dépité, je n'ai d'autre choix que de rm -r le dossier www, et recloner complètement le dossier du projet sur le serveur. Après reclonage, ça refonctionne. Si je refais des modifs sur truc.php sous windows, que je commit et que je push, tout va bien, le pull sur le serveur aboutit sans encombre. Si je crée des nouveaux fichiers, ça fonctionne aussi. Mais dès que je touche un ancien fichier que je n'ai pas touché depuis la migration depuis SVN, ça recommence et je suis de nouveau bon pour tout virer et tout recloner.

Est-ce qu'il n'y aurait pas un moyen de résoudre définitivement ce problème à la con ? Je n'ai pas envie de mettre le boxon et d'être embêté sous windows après, je tiens absolument à ne pas commit dans le repos qui est sur le serveur web.

Merci pour vos réponses

+0 -0

Salut,

Les changements de core.autocrlf ne s'appliquent que lorsque que tu pull (ou checkout) depuis Windows ou lorsque tu commits depuis Linux. Mais si ton repo remote (ou les locaux sous Windows) sont dans un état un peu intermédiaire, ça fout le boxon. Je pense que tu vas être obligé de passer ton repository remote au peigne fin à coup de dos2unix sur tous les fichiers (pour avoir que du LF sur le remote) puis cloner des repo propres sous Windows (où tu auras des CRLF en local) et sous Linux (à partir duquel tu ne pourras balancer que du LF sur le remote).

Par ailleurs, pour le stashing, je te conseille de lire la page du git book qui en parle (et de manière générale, tout le bouquin qui est extrêmement bien fait, et si tu peux, lis le en anglais). Au passage, après un stashing, tu n'as pas besoin de faire un pull complet, merger ce qui a été déjà récupéré à partir du remote est suffisant : git merge FETCH_HEAD.

+0 -0

JE n'ai pas envie de cloner sous windows, et si possible éviter de commit sous linux pour ne pas foutre la merde dans la version windows par après.

Parce que si je passe tous les fichiers en dos2unix sous linux, alors je serai obligé de commit non ? A moins de transformer aussi les fichiers de l'index que GIT prend pour référence. Ca ferait sûrement foirer les hash. Je n'ai aucune idée si les hash sont pris sur les fichiers en CRLF ou en LF, mais si côté linux je fais git status, un grand nombre de fichiers aparaissent en permanence comme étant modifiés alors que je ne les ai pas touchés, et, plus bizarre, git reset –hard ou git checkout les remet dans un état où ils apparaissent quand même comme modifiés. C'est en fait pour ça que le pull ou le checkout est systématiquement refusé. Donc là aussi il y a un bug.

Tiens d'ailleurs, ma version de dos2unix/unix2dos merdouille quand le fichier à convertir contient de l'UTF-8. IL me vire carrément tous les caractères >127 pour les remplacer par des NULL.

ET recloner la version windows ça me casse un peu les pieds, il y a plein de fichiers genre des images qui ne sont pas versionnées (parce que ça ne sert à rien) ; si je peux éviter ça m'arrangerais vraiment beaucoup.

Est-ce que je peux checker rapidement si un fichier sous linux est en LF ou CRLF ? nano peut ouvrir les deux donc je ne le vois pas.

C'est vraiment un problème à la con.

Le bouquin sur GIT je l'avais déjà lu, ou du moins en partie, mais dans sa version traduite. Si je me souviens bien c'est d'ailleurs dans le bouquin que j'ai trouvé la procédure pour convertir mon repos SVN en GIT. IL est super bien expliqué.

Merci.

+0 -0

JE n'ai pas envie de cloner sous windows, et si possible éviter de commit sous linux

Je capte pas, pourquoi tu as un dépôt Linux si tu ne t'en sers pas ?

pour ne pas foutre la merde dans la version windows par après.

Pourquoi tu voudrais que ça foute la merde ?

J'ai du mal à comprendre l'organisation général de tes repos et ta façon de travailler. Le moyen le plus simple pour pouvoir travailler sous Linux et sous Windows sur le même projet, c'est d'avoir le remote en LF, et les options de core.autocrlf comme tu les as mises. Ça assure d'une part de ne pas pouvoir commiter en CRLF sur le remote depuis les dépôts locaux (les fichiers seront automatiquement changés en LF), et de travailler en local avec CRLF sous Windows (les fichiers seront automatiquement changés en CRLF lors d'un checkout).

Parce que si je passe tous les fichiers en dos2unix sous linux, alors je serai obligé de commit non ?

Ben… Les changements vont pas se propager tout seuls, il faudra plus que commit, il faudra push aussi.

A moins de transformer aussi les fichiers de l'index que GIT prend pour référence.

Je comprends pas ce que tu veux dire.

Ca ferait sûrement foirer les hash. Je n'ai aucune idée si les hash sont pris sur les fichiers en CRLF ou en LF,

Euh… Les hash sont calculés avec l'état des fichiers quand tu commites.

mais si côté linux je fais git status, un grand nombre de fichiers aparaissent en permanence comme étant modifiés alors que je ne les ai pas touchés, et, plus bizarre, git reset –hard ou git checkout les remet dans un état où ils apparaissent quand même comme modifiés.

Comme je le comprends, ton remote est avec des CRLF et les fichiers sont changés en LF en local. C'est étrange.

C'est en fait pour ça que le pull ou le checkout est systématiquement refusé. Donc là aussi il y a un bug.

Tiens d'ailleurs, ma version de dos2unix/unix2dos merdouille quand le fichier à convertir contient de l'UTF-8. IL me vire carrément tous les caractères >127 pour les remplacer par des NULL.

Tu as un exemple de fichier ?

Est-ce que je peux checker rapidement si un fichier sous linux est en LF ou CRLF ? nano peut ouvrir les deux donc je ne le vois pas.

Regarde ce post sur SE (et le sujet de manière général, mais c'est la réponse que je trouve la plus simple).

Je capte pas, pourquoi tu as un dépôt Linux si tu ne t'en sers pas ?

JE ne travaille pas sous linux. Le dépôt linux est dans le dossier www du virtual host d'apache. Il sert à mettre à jour automatiquement le site quand je push.

En fait j'ai 3 dépôts :

  • Celui qui est sous windows avec lequel je travaille en local
  • Le repos de stockage en mode bare dans /home/git/monsite.com.git sur le serveur.
  • Le repos qui est dans le répertoire web sur /home/www/monsite.com/html/

J'ai mis un hook dans le repos bare pour que les modifs au push depuis windows soient automatiquement répercutés sur le site.

Quand je dis que je dois recloner le dépôt, en fait je clone /home/git/monsite.com.git dans /home/www/monsite.com/html.

J'aurais pu faire un système qui push direct dans /home/www/monsite.com/html, mais je voulais être sûr que le site est toujours sur la dernière version de master et pas autre chose. Par méconnaissance, ja'dmets, je préfèrais ne pas prendre le risque et de me retrouver tout à coup avec un site en ligne qui correspond à la branche random123 parce que c'est la dernière que j'ai push, ou je ne sais quoi. Je l'ai fait à la SVN avec un serveur de stockage au milieu, ça me paraissait plus sûr. ET comme ça je peux faire un backup du serveur bare tous les soirs avec un petit cron, accessoirement.

Le moyen le plus simple pour pouvoir travailler sous Linux et sous Windows sur le même projet, c'est d'avoir le remote en LF, et les options de core.autocrlf comme tu les as mises. Ça assure d'une part de ne pas pouvoir commiter en CRLF sur le remote depuis les dépôts locaux (les fichiers seront automatiquement changés en LF), et de travailler en local avec CRLF sous Windows (les fichiers seront automatiquement changés en CRLF lors d'un checkout).

C'est bien ce que j'avais déjà lu sur stackoverflow.

Euh… Les hash sont calculés avec l'état des fichiers quand tu commites.

Ben justement. Ce que je veux dire par là c'est que je ne sais pas si GIT stocke mes fichiers en LF ou en CRLF. J'ai l'impression que c'est l'un alors qu'il s'attend à l'autre.

Comme je le comprends, ton remote est avec des CRLF et les fichiers sont changés en LF en local. C'est étrange.

Ca ressemble effectivement à un truc comme ça. Je vais essayer de regarder avec ce que tu me proposes, si les fichiers sont en LF ou en CRLF.

Tu as un exemple de fichier ?

C'est la version windows de dos2unix/unix2dos qui me fait ça. La version linux a l'air de fonctionner elle.

+0 -0

En fait j'ai 3 dépôts…

Ah OK, c'est beaucoup plus clair maintenant. Ça me parait bien comme organisation.

Je l'ai fait à la SVN avec un serveur de stockage au milieu, ça me paraissait plus sûr.

Ça part contre, je ne comprends pas. Où intervient SVN dans l'affaire ? C'est peut être lui qui fout le boxon (je ne sais pas comment il gère l'histoire des CRLF, et avec svn, je m'attends à tout ^^ ).

Ca ressemble effectivement à un truc comme ça. Je vais essayer de regarder avec ce que tu me proposes, si les fichiers sont en LF ou en CRLF.

Tu as un exemple de fichier ?

C'est la version windows de dos2unix/unix2dos qui me fait ça. La version linux a l'air de fonctionner elle.

OK, donc effectivement, vérifie que les fichiers sur /home/git/... ont bien des fins de lignes en LF. Si ce n'est pas le cas, mets temporairement l'option core.autocrlf a false côté Linux, récupère la version dans /home/git/, passe un coup de dos2unix sur tous les fichiers et push sur /home/git. Après, tu peux remettre l'option core.autocrlf à input, et croiser les doigts pour que tout se passe bien en faisant un pull sous Windows.

Ça part contre, je ne comprends pas. Où intervient SVN dans l'affaire ? C'est peut être lui qui fout le boxon (je ne sais pas comment il gère l'histoire des CRLF, et avec svn, je m'attends à tout

SVN ne m'a jamais rien demandé à propos des fins de ligne. Je pense qu'il gère ça de manière complètement transparente. GIT ne peut pas être aussi sympa et simple puisqu'il calcule des empreintes du contenu des fichiers, à précision binaire.

Du coup tout pendant que j'étais avec SVN, les fichiers étaient tous probablement stockés inchangés, avec des CRLF donc puisque je travaille sous windows. Lors de l'import SVN->GIT, il n'a sûrement rien changé, il les a gardé en CRLF. L'import de tout le dépôt avec les 500 et quelques révisions a pris plus d'une heure.

Mais ce que je voulais dire ici par « je l'ai fait à la SVN » c'est que j'ai créé un dépôt spécial qui sert uniquement de stockage; alors que j'aurais pu, si j'ai bien compris, ne pas en avoir besoin et faire la même chose avec seulement 2 dépôts.

En fait l'erreur que j'ai probablement faite à ce moment-là c'est que je n'avais pas les bonnes valeurs pour core.autocrlf; j'ignorais complètement la situation et c'est quand j'ai commencé d'avoir ces problèmes que j'ai fait des recherches et que je suis tombé sur cette option. Si c'est la meilleure solution pour éviter les problèmes, comment se fait-il que 'true' sous windows et 'input' sous linux ne soit pas la configuration par défaut ?

OK, donc effectivement, vérifie que les fichiers sur /home/git/… ont bien des fins de lignes en LF.

J'ai vérifié avec les infos donnés dans ton lien. En fait c'était même plus simple, je ne savais pas que la commande file fournissait l'information. Du coup j'ai fait file *.php dans le répertoire du site et la situation est tordue :

  • Les fichiers que j'ai modifié au moins une fois depuis la migration depuis SVN sont bien en LF
  • Tous les fichiers que je n'ai pas touché depuis la migration à partir de SVN sont en CRLF

Je viens d'essayer de cloner mon dépôt sur un autre PC windows et j'ai le problème inverse, c'est sous windows qu'il ne veut plus pull ou checkout. Le dépôt initial sur le premier windows fonctionne toujours lui.

Du coup, apparament, j'ai deux choix :

  • Faire ce que tu proposes, c'est-à-dire faire un dos2unix de tous les fichiers sous linux, commit, push, puis pull sous windows
  • Je pense que je devrais pouvoir y arriver autrement en faisant un touch sur tous les fichiers sous windows, commit, push, puis un ultime clonage tout neuf sous linux. GIT va croire que tous les fichiers ont été modifiés et du coup il les pushera tous en LF grâce à l'option core.autocrlff. C'est nul parce que ça va plomber l'historique, mais tant pis.
+0 -0

SVN ne m'a jamais rien demandé à propos des fins de ligne. Je pense qu'il gère ça de manière complètement transparente.

Non en fait, il ne gère pas ça du tout. Du coup, oui, il n'y a pas touché, et tous tes fichiers étaient en CRLF. Mais si tu avais commencé à changé les fichiers en LF, ça aurait merdé de la même façon, sauf qu'il n'y aurait aucune option comme Git pour gérer ça proprement.

GIT ne peut pas être aussi sympa et simple puisqu'il calcule des empreintes du contenu des fichiers, à précision binaire.

SVN sait faire la différence entre CRLF et LF. Ce qui a foutu le boxon avec Git, c'est que tu avais un hybride complet.

Du coup tout pendant que j'étais avec SVN, les fichiers étaient tous probablement stockés inchangés, avec des CRLF donc puisque je travaille sous windows. Lors de l'import SVN->GIT, il n'a sûrement rien changé, il les a gardé en CRLF. L'import de tout le dépôt avec les 500 et quelques révisions a pris plus d'une heure.

Ça prend tout son sens, en effet, ça explique la situation hybride que tu décris plus loin.

Si c'est la meilleure solution pour éviter les problèmes, comment se fait-il que 'true' sous windows et 'input' sous linux ne soit pas la configuration par défaut ?

C'est la meilleure solution pour bosser sous Linux et sous Windows en même temps. Comme Git est pensé avant tout comme un outil pour des systèmes Unix-like, il n'y a pas de raison d'activer des conversions implicites, l'utilisateur peut très bien avoir besoin de garder des fichiers avec des CRLF dedans. De même si tu bosses uniquement sous Windows, il n'y a rien à faire de spécial.

Du coup, apparament, j'ai deux choix :

  • Faire ce que tu proposes, c'est-à-dire faire un dos2unix de tous les fichiers sous linux, commit, push, puis pull sous windows
  • Je pense que je devrais pouvoir y arriver autrement en faisant un touch sur tous les fichiers sous windows, commit, push, puis un ultime clonage tout neuf sous linux. GIT va croire que tous les fichiers ont été modifiés et du coup il les pushera tous en LF grâce à l'option core.autocrlff. C'est nul parce que ça va plomber l'historique, mais tant pis.

De toute façon, oui, tu vas être obligé de massacrer ton historique, ça tu n'as pas le choix maintenant que la situation est aussi étrange. Par contre, faire un touch ne servira strictement à rien, Git traque le contenu, pas les fichiers. touch ne fait que changer la date de dernière modification, mais l'empreinte SHA du fichier reste la même.

EDIT : j'y pense, si sous Linux, les fichiers apparaissent comme modifiés, tu n'as même pas besoin de faire la conversion avec dos2unix à la main : l'option autocrlf s'en est déjà chargé. Tu as juste à git commit -a et git push directement, je pense.

+0 -0

EDIT : j'y pense, si sous Linux, les fichiers apparaissent comme modifiés, tu n'as même pas besoin de faire la conversion avec dos2unix à la main : l'option autocrlf s'en est déjà chargé. Tu as juste à git commit -a et git push directement, je pense.

Non je ne pense pas, puisque les fichiers qui apparaissent comme toujours modifiés sous linux sont ceux que je n'ai pas touché et qui sont toujours en CRLF, alors qu'ils devraient être en LF. JE dois donc les convertir non ?

J'ai essayé sur quelques fichiers, ta première solution a l'air de fonctionner mais elle me fout le bordel. Le merge automatique de GIT foire sous windows et je ne sais pas ce que je dois faire pour qu'il n'écrase rien. Je vais tester mon autre idée.

+0 -0

Non je ne pense pas, puisque les fichiers qui apparaissent comme toujours modifiés sous linux sont ceux que je n'ai pas touché et qui sont toujours en CRLF, alors qu'ils devraient être en LF. JE dois donc les convertir non ?

Tu as testé sur ton dépôt Linux (pas le git, l'autre) si les fichiers apparaissant comme modifiés sont en CRLF ? M'est avis qu'ils sont passés en LF par Git, et donc apparaissent comme modifiés par rapport à la version du dépôt qui elle est en CRLF. Si c'est le cas, tu aurais alors juste à commit et push directement.

J'ai essayé sur quelques fichiers, ta première solution a l'air de fonctionner mais elle me fout le bordel. Le merge automatique de GIT foire sous windows

Qu'est-ce que ça dit ? Et avais tu bien mis l'option autocrlf à false et te caler sur l'état du repo avant de faire la manip ?

Tu as testé sur ton dépôt Linux (pas le git, l'autre) si les fichiers apparaissant comme modifiés sont en CRLF ?

Oui, sur le dépôt /home/www/monsite.com/html ils sont en CRLF.

Sur le dépôt bare, je ne sais pas comment je suis supposé tester ça, si c'est ce que tu me demandes.

Je vais réessayer. L'erreur disait que le merge automatique a échoué et et je dois commit pour résoudre. Le truc c'est que mes fichiers ont été pollués par des marques à la con et qu'en gros c'est aussi chiant à gérer qu'un conflit SVN à l'ancienne. Pas envie de perdre du temps à comprendre le bouzin, tu écrases et RAF. Mais j'ai peur d'écraser quelque chose et de renforcer encore le bordel.

+0 -0

Au temps pour moi, ça marche. Je dois quand même passer dos2unix mais ça marche.

J'avais bien changé le paramètre globalement, mais j'ai oublié de le faire aussi spécifiquement pour le dépôt.

Le touch sous windows fonctionne aussi en fait.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte