2017-09-12 2 views
1

J'ai un git repo avec une branche de publication ("master") et quelques autres branches à des fins de développement. En tant que projet incorporé, certains fichiers .tbl sont générés ou modifiés à chaque compilation. Je dois garder les fichiers tbl dans la branche master non modifiés (à moins qu'il y ait une nouvelle version) et donc empêcher la fusion avec d'autres branches de modifier ces fichiers tbl.Empêcher la fusion sur la branche principale pour un type de fichier - Git

J'ai déjà essayé de déclarer les fichiers tbl comme binaires ou en utilisant *.tbl merge=ours mais comme spécifié dans https://git-scm.com/docs/git-merge cela fonctionne uniquement en cas de conflit.

Est-ce que quelqu'un a déjà rencontré une situation similaire?

Répondre

1

Vous pouvez définir *.tbl merge=ours dans le fichier .gitattributes, et d'ajouter un paramètre global:

git config --global merge.ours.driver true 

Il ne conserver que la version du fichier *.tbl sur master branche pour une partie des situations (comme les deux premières situations ci-dessous).

Lors de la fusion d'autres branches dans master, il a trois situations pour le fichier *.tbl: le fichier *.tbl

  • a-conflit lors de la fusion: cela signifie que la version du fichier *.tbl dans d'autres branches est différent de la version dans la branche master. Puisque vous avez défini des stratégies de fusion pour le *.tbl comme le nôtre. Alors la version de *.tbl sur la branche master sera ketp.
  • n'a pas changé le fichier *.tbl des deux côtés: cela signifie que les deux versions de fichier *.tbl sur master les autres branches sont les mêmes, donc ne vous inquiétez pas le fichier *.tbl sur master branche est écrasée.
  • Modifier le fichier *.tbl que de l'autre côté des branches: cela écrase le fichier *.tbl avec la version des autres branches depuis git merge utiliser la stratégie de fusion récursive. Donc, vous devez changer le fichier *.tbl avec la version sur la branche master. Ainsi, vous pouvez utiliser les commandes ci-dessous:

    git merge branchname 
    git checkout HEAD~ *.tbl 
    git commit -m 'switch the file as the version on master' 
    

BTW, si le fichier *.tbl est pas nécessaire de contrôle de version sur les branches non-maître, vous ne pouvez gérer le fichier sur la branche master.


Ou il y a une autre option, vous pouvez consulter: gérer le fichier *.tbl dans une branche séparée (telle branche tbl).

Même le fichier *.tbl peut être écrasé sur la branche master, la version sur la branche tbl doit être correcte.Lorsque vous avez besoin d'une nouvelle version, vous pouvez checkout la version de tbl branche à branche master:

git checkout master 
git checkout tbl *.tbl 
git commit -m 'recovery the version as last release' 

Ensuite, vous pouvez préparer à la nouvelle version.

Après avoir relâché sur master branche, vous pouvez mettre à jour le fichier sur tbl branche:

git checkout tbl 
git checkout master *.tbl 
git commit -m 'update the file with new release version on tbl branch' 
+0

En fait ce n'est pas tout à fait vrai, car il y a une troisième situation: si je modifie le fichier .tbl seulement dans la branche develop et ensuite je fusionne cette branche sur le master, je n'obtiendrai pas de conflit changements de la branche de développement. – ArenaLor

+0

'git merge -sons' n'est pas correct non plus: il dit à Git de * complètement ignorer * l'autre branche. C'est bien pour les fichiers '* .tbl', mais vraisemblablement tous les * autres * fichiers devraient être fusionnés. – torek

+0

J'ai mis à jour ma réponse, et pour la situation le fichier '* .tbl' a seulement changé sur d'autres branches, il a besoin d'étapes supplémentaires pour passer les fichiers à la version originale sur la branche' master'. –

1

Git n'a pas de stratégie de fusion pour ce cas.

À moins d'écrire votre propre fusion git merge -s ArenaLor appellera stratégie-git-merge-ArenaLor, et vous auriez à écrire cette commande, mais il ferait tout ce que vous vouliez-il est, comme vous avez observé, aucun moyen d'obtenir Git de faire une fusion à trois voies normale sur la plupart des fichiers, mais de toujours garder une version particulière d'un ensemble particulier de fichiers en place.

Fondamentalement, la plupart des stratégies fusionner effectuer les tâches suivantes:

  1. Identifier commit fusion-base. Appelons ce commit B pour plus de commodité. B a un tas de fichiers enregistrés comme instantanés; d'ici, les deux autres branches divergent.
  2. Diffère la base de fusion par rapport à chaque extrémité de branche, afin de déterminer quels fichiers sont modifiés dans quelles branches. Par exemple, il est plus simple d'appeler les deux bouts de branche L et R, pour Gauche et Droite, ou Local et Distant, ou Ours et Theirs (il n'y a pas L dans le mot "notre" mais c'est ainsi Git travaille avec les stratégies récursives et de résolution habituelles).
  3. Construire le nouveau commit à faire en prenant chaque fichier de B (pas de changement dans une branche), L (le fichier est modifié que dans notre branche locale/côté gauche), R (fichier est modifié uniquement dans leur branche distante/côté droit), ou-si le fichier est modifié en les deux des deux commits de branchement-par combinant les modifications.

L'option *.tbl merge=ours dans un fichier .gitattributes affecte uniquement étape 3, puis que si le fichier est modifié dans les deux branche pointe engage. Cela signifie qu'un pilote de fusion est uniquement exécuté si Git doit combiner les modifications. Peu importe si les changements ont des conflits; ce qui importe est que les deux L et R ont modifié certains fichiers F par rapport à ce qui était dans la base de commit de fusion B. Cependant, ces décisions sont toutes prises par la stratégie de fusion. Si vous écrivez la vôtre, vous pouvez prendre vos propres décisions.Notez que la stratégie -s ours est tout à fait différente: au lieu de faire les trois étapes ci-dessus, il le fait un pas:

  1. Prenez tous les fichiers de L. Nous n'avons même pas besoin de trouver B, ou regarder le contenu de R. Gardez juste ce qui est dans l'index en ce moment et faites un commit de fusion avec parent 1 = L et parent 2 = R.

Cela fait ce que vous voulez pour vos fichiers *.tbl, mais est faux pour tous vos autres fichiers, donc ce n'est pas approprié ici.

+0

Il n'y a donc aucun moyen d'obtenir ce que je veux, sauf peut-être pour écrire ma propre stratégie de fusion. – ArenaLor

+0

Droite. L'approche habituelle pour le type de fichier dont vous parlez ici est de ne pas le valider du tout: commit, à la place, une sorte de fichier "sample" ou "default" (configuration) et le convertir en le fichier cible qui est alors un fichier non suivi (qui peut être ajouté à '.gitignore' pour empêcher Git de se plaindre). – torek

+0

Moi et mes coéquipiers avons pensé à faire quelque chose comme ce que vous avez dit mais notre conclusion est que ça ne peut pas marcher. Notre situation est la suivante: chaque fois que nous compilons notre système d'exploitation embarqué, le tbl est modifié; il y a alors un certain nombre d'autres composants qui dépendent du tbl lors de la compilation. Donc, si j'ai un tbl invalide (peut-être parce que j'essaie quelque chose de nouveau dans le système d'exploitation) et que j'essaie de compiler un composant pour le relâcher, ce composant sera invalide et non reconnu par le système d'exploitation. – ArenaLor