git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
blob 92010b062e08678fcfb0a143f75bbd4b07bfcf4b 46761 bytes (raw)
name: Documentation/gitattributes.txt 	 # note: path name is non-authoritative(*)

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
 
gitattributes(5)
================

NAME
----
gitattributes - Defining attributes per path

SYNOPSIS
--------
$GIT_DIR/info/attributes, .gitattributes


DESCRIPTION
-----------

A `gitattributes` file is a simple text file that gives
`attributes` to pathnames.

Each line in `gitattributes` file is of form:

	pattern	attr1 attr2 ...

That is, a pattern followed by an attributes list,
separated by whitespaces. Leading and trailing whitespaces are
ignored. Lines that begin with '#' are ignored. Patterns
that begin with a double quote are quoted in C style.
When the pattern matches the path in question, the attributes
listed on the line are given to the path.

Each attribute can be in one of these states for a given path:

Set::

	The path has the attribute with special value "true";
	this is specified by listing only the name of the
	attribute in the attribute list.

Unset::

	The path has the attribute with special value "false";
	this is specified by listing the name of the attribute
	prefixed with a dash `-` in the attribute list.

Set to a value::

	The path has the attribute with specified string value;
	this is specified by listing the name of the attribute
	followed by an equal sign `=` and its value in the
	attribute list.

Unspecified::

	No pattern matches the path, and nothing says if
	the path has or does not have the attribute, the
	attribute for the path is said to be Unspecified.

When more than one pattern matches the path, a later line
overrides an earlier line.  This overriding is done per
attribute.

The rules by which the pattern matches paths are the same as in
`.gitignore` files (see linkgit:gitignore[5]), with a few exceptions:

  - negative patterns are forbidden

  - patterns that match a directory do not recursively match paths
    inside that directory (so using the trailing-slash `path/` syntax is
    pointless in an attributes file; use `path/**` instead)

When deciding what attributes are assigned to a path, Git
consults `$GIT_DIR/info/attributes` file (which has the highest
precedence), `.gitattributes` file in the same directory as the
path in question, and its parent directories up to the toplevel of the
work tree (the further the directory that contains `.gitattributes`
is from the path in question, the lower its precedence). Finally
global and system-wide files are considered (they have the lowest
precedence).

When the `.gitattributes` file is missing from the work tree, the
path in the index is used as a fall-back.  During checkout process,
`.gitattributes` in the index is used and then the file in the
working tree is used as a fall-back.

If you wish to affect only a single repository (i.e., to assign
attributes to files that are particular to
one user's workflow for that repository), then
attributes should be placed in the `$GIT_DIR/info/attributes` file.
Attributes which should be version-controlled and distributed to other
repositories (i.e., attributes of interest to all users) should go into
`.gitattributes` files. Attributes that should affect all repositories
for a single user should be placed in a file specified by the
`core.attributesFile` configuration option (see linkgit:git-config[1]).
Its default value is $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME
is either not set or empty, $HOME/.config/git/attributes is used instead.
Attributes for all users on a system should be placed in the
`$(prefix)/etc/gitattributes` file.

Sometimes you would need to override a setting of an attribute
for a path to `Unspecified` state.  This can be done by listing
the name of the attribute prefixed with an exclamation point `!`.


EFFECTS
-------

Certain operations by Git can be influenced by assigning
particular attributes to a path.  Currently, the following
operations are attributes-aware.

Checking-out and checking-in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These attributes affect how the contents stored in the
repository are copied to the working tree files when commands
such as 'git checkout' and 'git merge' run.  They also affect how
Git stores the contents you prepare in the working tree in the
repository upon 'git add' and 'git commit'.

`text`
^^^^^^

This attribute enables and controls end-of-line normalization.  When a
text file is normalized, its line endings are converted to LF in the
repository.  To control what line ending style is used in the working
directory, use the `eol` attribute for a single file and the
`core.eol` configuration variable for all text files.
Note that `core.autocrlf` overrides `core.eol`

Set::

	Setting the `text` attribute on a path enables end-of-line
	normalization and marks the path as a text file.  End-of-line
	conversion takes place without guessing the content type.

Unset::

	Unsetting the `text` attribute on a path tells Git not to
	attempt any end-of-line conversion upon checkin or checkout.

Set to string value "auto"::

	When `text` is set to "auto", the path is marked for automatic
	end-of-line conversion.  If Git decides that the content is
	text, its line endings are converted to LF on checkin.
	When the file has been committed with CRLF, no conversion is done.

Unspecified::

	If the `text` attribute is unspecified, Git uses the
	`core.autocrlf` configuration variable to determine if the
	file should be converted.

Any other value causes Git to act as if `text` has been left
unspecified.

`eol`
^^^^^

This attribute sets a specific line-ending style to be used in the
working directory.  It enables end-of-line conversion without any
content checks, effectively setting the `text` attribute.  Note that
setting this attribute on paths which are in the index with CRLF line
endings may make the paths to be considered dirty.  Adding the path to
the index again will normalize the line endings in the index.

Set to string value "crlf"::

	This setting forces Git to normalize line endings for this
	file on checkin and convert them to CRLF when the file is
	checked out.

Set to string value "lf"::

	This setting forces Git to normalize line endings to LF on
	checkin and prevents conversion to CRLF when the file is
	checked out.

Backwards compatibility with `crlf` attribute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For backwards compatibility, the `crlf` attribute is interpreted as
follows:

------------------------
crlf		text
-crlf		-text
crlf=input	eol=lf
------------------------

End-of-line conversion
^^^^^^^^^^^^^^^^^^^^^^

While Git normally leaves file contents alone, it can be configured to
normalize line endings to LF in the repository and, optionally, to
convert them to CRLF when files are checked out.

If you simply want to have CRLF line endings in your working directory
regardless of the repository you are working with, you can set the
config variable "core.autocrlf" without using any attributes.

------------------------
[core]
	autocrlf = true
------------------------

This does not force normalization of text files, but does ensure
that text files that you introduce to the repository have their line
endings normalized to LF when they are added, and that files that are
already normalized in the repository stay normalized.

If you want to ensure that text files that any contributor introduces to
the repository have their line endings normalized, you can set the
`text` attribute to "auto" for _all_ files.

------------------------
*	text=auto
------------------------

The attributes allow a fine-grained control, how the line endings
are converted.
Here is an example that will make Git normalize .txt, .vcproj and .sh
files, ensure that .vcproj files have CRLF and .sh files have LF in
the working directory, and prevent .jpg files from being normalized
regardless of their content.

------------------------
*               text=auto
*.txt		text
*.vcproj	text eol=crlf
*.sh		text eol=lf
*.jpg		-text
------------------------

NOTE: When `text=auto` conversion is enabled in a cross-platform
project using push and pull to a central repository the text files
containing CRLFs should be normalized.

From a clean working directory:

-------------------------------------------------
$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"
-------------------------------------------------

If any files that should not be normalized show up in 'git status',
unset their `text` attribute before running 'git add -u'.

------------------------
manual.pdf	-text
------------------------

Conversely, text files that Git does not detect can have normalization
enabled manually.

------------------------
weirdchars.txt	text
------------------------

If `core.safecrlf` is set to "true" or "warn", Git verifies if
the conversion is reversible for the current setting of
`core.autocrlf`.  For "true", Git rejects irreversible
conversions; for "warn", Git only prints a warning but accepts
an irreversible conversion.  The safety triggers to prevent such
a conversion done to the files in the work tree, but there are a
few exceptions.  Even though...

- 'git add' itself does not touch the files in the work tree, the
  next checkout would, so the safety triggers;

- 'git apply' to update a text file with a patch does touch the files
  in the work tree, but the operation is about text files and CRLF
  conversion is about fixing the line ending inconsistencies, so the
  safety does not trigger;

- 'git diff' itself does not touch the files in the work tree, it is
  often run to inspect the changes you intend to next 'git add'.  To
  catch potential problems early, safety triggers.


`working-tree-encoding`
^^^^^^^^^^^^^^^^^^^^^^^

Git recognizes files encoded in ASCII or one of its supersets (e.g.
UTF-8, ISO-8859-1, ...) as text files. Files encoded in certain other
encodings (e.g. UTF-16) are interpreted as binary and consequently
built-in Git text processing tools (e.g. 'git diff') as well as most Git
web front ends do not visualize the contents of these files by default.

In these cases you can tell Git the encoding of a file in the working
directory with the `working-tree-encoding` attribute. If a file with this
attribute is added to Git, then Git reencodes the content from the
specified encoding to UTF-8. Finally, Git stores the UTF-8 encoded
content in its internal data structure (called "the index"). On checkout
the content is reencoded back to the specified encoding.

Please note that using the `working-tree-encoding` attribute may have a
number of pitfalls:

- Alternative Git implementations (e.g. JGit or libgit2) and older Git
  versions (as of March 2018) do not support the `working-tree-encoding`
  attribute. If you decide to use the `working-tree-encoding` attribute
  in your repository, then it is strongly recommended to ensure that all
  clients working with the repository support it.

  For example, Microsoft Visual Studio resources files (`*.rc`) or
  PowerShell script files (`*.ps1`) are sometimes encoded in UTF-16.
  If you declare `*.ps1` as files as UTF-16 and you add `foo.ps1` with
  a `working-tree-encoding` enabled Git client, then `foo.ps1` will be
  stored as UTF-8 internally. A client without `working-tree-encoding`
  support will checkout `foo.ps1` as UTF-8 encoded file. This will
  typically cause trouble for the users of this file.

  If a Git client, that does not support the `working-tree-encoding`
  attribute, adds a new file `bar.ps1`, then `bar.ps1` will be
  stored "as-is" internally (in this example probably as UTF-16).
  A client with `working-tree-encoding` support will interpret the
  internal contents as UTF-8 and try to convert it to UTF-16 on checkout.
  That operation will fail and cause an error.

- Reencoding content to non-UTF encodings can cause errors as the
  conversion might not be UTF-8 round trip safe. If you suspect your
  encoding to not be round trip safe, then add it to
  `core.checkRoundtripEncoding` to make Git check the round trip
  encoding (see linkgit:git-config[1]). SHIFT-JIS (Japanese character
  set) is known to have round trip issues with UTF-8 and is checked by
  default.

- Reencoding content requires resources that might slow down certain
  Git operations (e.g 'git checkout' or 'git add').

Use the `working-tree-encoding` attribute only if you cannot store a file
in UTF-8 encoding and if you want Git to be able to process the content
as text.

As an example, use the following attributes if your '*.ps1' files are
UTF-16 encoded with byte order mark (BOM) and you want Git to perform
automatic line ending conversion based on your platform.

------------------------
*.ps1		text working-tree-encoding=UTF-16
------------------------

Use the following attributes if your '*.ps1' files are UTF-16 little
endian encoded without BOM and you want Git to use Windows line endings
in the working directory. Please note, it is highly recommended to
explicitly define the line endings with `eol` if the `working-tree-encoding`
attribute is used to avoid ambiguity.

------------------------
*.ps1		text working-tree-encoding=UTF-16LE eol=CRLF
------------------------

You can get a list of all available encodings on your platform with the
following command:

------------------------
iconv --list
------------------------

If you do not know the encoding of a file, then you can use the `file`
command to guess the encoding:

------------------------
file foo.ps1
------------------------


`ident`
^^^^^^^

When the attribute `ident` is set for a path, Git replaces
`$Id$` in the blob object with `$Id:`, followed by the
40-character hexadecimal blob object name, followed by a dollar
sign `$` upon checkout.  Any byte sequence that begins with
`$Id:` and ends with `$` in the worktree file is replaced
with `$Id$` upon check-in.


`filter`
^^^^^^^^

A `filter` attribute can be set to a string value that names a
filter driver specified in the configuration.

A filter driver consists of a `clean` command and a `smudge`
command, either of which can be left unspecified.  Upon
checkout, when the `smudge` command is specified, the command is
fed the blob object from its standard input, and its standard
output is used to update the worktree file.  Similarly, the
`clean` command is used to convert the contents of worktree file
upon checkin. By default these commands process only a single
blob and terminate. If a long running `process` filter is used
in place of `clean` and/or `smudge` filters, then Git can process
all blobs with a single filter command invocation for the entire
life of a single Git command, for example `git add --all`. If a
long running `process` filter is configured then it always takes
precedence over a configured single blob filter. See section
below for the description of the protocol used to communicate with
a `process` filter.

One use of the content filtering is to massage the content into a shape
that is more convenient for the platform, filesystem, and the user to use.
For this mode of operation, the key phrase here is "more convenient" and
not "turning something unusable into usable".  In other words, the intent
is that if someone unsets the filter driver definition, or does not have
the appropriate filter program, the project should still be usable.

Another use of the content filtering is to store the content that cannot
be directly used in the repository (e.g. a UUID that refers to the true
content stored outside Git, or an encrypted content) and turn it into a
usable form upon checkout (e.g. download the external content, or decrypt
the encrypted content).

These two filters behave differently, and by default, a filter is taken as
the former, massaging the contents into more convenient shape.  A missing
filter driver definition in the config, or a filter driver that exits with
a non-zero status, is not an error but makes the filter a no-op passthru.

You can declare that a filter turns a content that by itself is unusable
into a usable content by setting the filter.<driver>.required configuration
variable to `true`.

Note: Whenever the clean filter is changed, the repo should be renormalized:
$ git add --renormalize .

For example, in .gitattributes, you would assign the `filter`
attribute for paths.

------------------------
*.c	filter=indent
------------------------

Then you would define a "filter.indent.clean" and "filter.indent.smudge"
configuration in your .git/config to specify a pair of commands to
modify the contents of C programs when the source files are checked
in ("clean" is run) and checked out (no change is made because the
command is "cat").

------------------------
[filter "indent"]
	clean = indent
	smudge = cat
------------------------

For best results, `clean` should not alter its output further if it is
run twice ("clean->clean" should be equivalent to "clean"), and
multiple `smudge` commands should not alter `clean`'s output
("smudge->smudge->clean" should be equivalent to "clean").  See the
section on merging below.

The "indent" filter is well-behaved in this regard: it will not modify
input that is already correctly indented.  In this case, the lack of a
smudge filter means that the clean filter _must_ accept its own output
without modifying it.

If a filter _must_ succeed in order to make the stored contents usable,
you can declare that the filter is `required`, in the configuration:

------------------------
[filter "crypt"]
	clean = openssl enc ...
	smudge = openssl enc -d ...
	required
------------------------

Sequence "%f" on the filter command line is replaced with the name of
the file the filter is working on.  A filter might use this in keyword
substitution.  For example:

------------------------
[filter "p4"]
	clean = git-p4-filter --clean %f
	smudge = git-p4-filter --smudge %f
------------------------

Note that "%f" is the name of the path that is being worked on. Depending
on the version that is being filtered, the corresponding file on disk may
not exist, or may have different contents. So, smudge and clean commands
should not try to access the file on disk, but only act as filters on the
content provided to them on standard input.

Long Running Filter Process
^^^^^^^^^^^^^^^^^^^^^^^^^^^

If the filter command (a string value) is defined via
`filter.<driver>.process` then Git can process all blobs with a
single filter invocation for the entire life of a single Git
command. This is achieved by using the long-running process protocol
(described in technical/long-running-process-protocol.txt).

When Git encounters the first file that needs to be cleaned or smudged,
it starts the filter and performs the handshake. In the handshake, the
welcome message sent by Git is "git-filter-client", only version 2 is
suppported, and the supported capabilities are "clean", "smudge", and
"delay".

Afterwards Git sends a list of "key=value" pairs terminated with
a flush packet. The list will contain at least the filter command
(based on the supported capabilities) and the pathname of the file
to filter relative to the repository root. Right after the flush packet
Git sends the content split in zero or more pkt-line packets and a
flush packet to terminate content. Please note, that the filter
must not send any response before it received the content and the
final flush packet. Also note that the "value" of a "key=value" pair
can contain the "=" character whereas the key would never contain
that character.
------------------------
packet:          git> command=smudge
packet:          git> pathname=path/testfile.dat
packet:          git> 0000
packet:          git> CONTENT
packet:          git> 0000
------------------------

The filter is expected to respond with a list of "key=value" pairs
terminated with a flush packet. If the filter does not experience
problems then the list must contain a "success" status. Right after
these packets the filter is expected to send the content in zero
or more pkt-line packets and a flush packet at the end. Finally, a
second list of "key=value" pairs terminated with a flush packet
is expected. The filter can change the status in the second list
or keep the status as is with an empty list. Please note that the
empty list must be terminated with a flush packet regardless.

------------------------
packet:          git< status=success
packet:          git< 0000
packet:          git< SMUDGED_CONTENT
packet:          git< 0000
packet:          git< 0000  # empty list, keep "status=success" unchanged!
------------------------

If the result content is empty then the filter is expected to respond
with a "success" status and a flush packet to signal the empty content.
------------------------
packet:          git< status=success
packet:          git< 0000
packet:          git< 0000  # empty content!
packet:          git< 0000  # empty list, keep "status=success" unchanged!
------------------------

In case the filter cannot or does not want to process the content,
it is expected to respond with an "error" status.
------------------------
packet:          git< status=error
packet:          git< 0000
------------------------

If the filter experiences an error during processing, then it can
send the status "error" after the content was (partially or
completely) sent.
------------------------
packet:          git< status=success
packet:          git< 0000
packet:          git< HALF_WRITTEN_ERRONEOUS_CONTENT
packet:          git< 0000
packet:          git< status=error
packet:          git< 0000
------------------------

In case the filter cannot or does not want to process the content
as well as any future content for the lifetime of the Git process,
then it is expected to respond with an "abort" status at any point
in the protocol.
------------------------
packet:          git< status=abort
packet:          git< 0000
------------------------

Git neither stops nor restarts the filter process in case the
"error"/"abort" status is set. However, Git sets its exit code
according to the `filter.<driver>.required` flag, mimicking the
behavior of the `filter.<driver>.clean` / `filter.<driver>.smudge`
mechanism.

If the filter dies during the communication or does not adhere to
the protocol then Git will stop the filter process and restart it
with the next file that needs to be processed. Depending on the
`filter.<driver>.required` flag Git will interpret that as error.

Delay
^^^^^

If the filter supports the "delay" capability, then Git can send the
flag "can-delay" after the filter command and pathname. This flag
denotes that the filter can delay filtering the current blob (e.g. to
compensate network latencies) by responding with no content but with
the status "delayed" and a flush packet.
------------------------
packet:          git> command=smudge
packet:          git> pathname=path/testfile.dat
packet:          git> can-delay=1
packet:          git> 0000
packet:          git> CONTENT
packet:          git> 0000
packet:          git< status=delayed
packet:          git< 0000
------------------------

If the filter supports the "delay" capability then it must support the
"list_available_blobs" command. If Git sends this command, then the
filter is expected to return a list of pathnames representing blobs
that have been delayed earlier and are now available.
The list must be terminated with a flush packet followed
by a "success" status that is also terminated with a flush packet. If
no blobs for the delayed paths are available, yet, then the filter is
expected to block the response until at least one blob becomes
available. The filter can tell Git that it has no more delayed blobs
by sending an empty list. As soon as the filter responds with an empty
list, Git stops asking. All blobs that Git has not received at this
point are considered missing and will result in an error.

------------------------
packet:          git> command=list_available_blobs
packet:          git> 0000
packet:          git< pathname=path/testfile.dat
packet:          git< pathname=path/otherfile.dat
packet:          git< 0000
packet:          git< status=success
packet:          git< 0000
------------------------

After Git received the pathnames, it will request the corresponding
blobs again. These requests contain a pathname and an empty content
section. The filter is expected to respond with the smudged content
in the usual way as explained above.
------------------------
packet:          git> command=smudge
packet:          git> pathname=path/testfile.dat
packet:          git> 0000
packet:          git> 0000  # empty content!
packet:          git< status=success
packet:          git< 0000
packet:          git< SMUDGED_CONTENT
packet:          git< 0000
packet:          git< 0000  # empty list, keep "status=success" unchanged!
------------------------

Example
^^^^^^^

A long running filter demo implementation can be found in
`contrib/long-running-filter/example.pl` located in the Git
core repository. If you develop your own long running filter
process then the `GIT_TRACE_PACKET` environment variables can be
very helpful for debugging (see linkgit:git[1]).

Please note that you cannot use an existing `filter.<driver>.clean`
or `filter.<driver>.smudge` command with `filter.<driver>.process`
because the former two use a different inter process communication
protocol than the latter one.


Interaction between checkin/checkout attributes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In the check-in codepath, the worktree file is first converted
with `filter` driver (if specified and corresponding driver
defined), then the result is processed with `ident` (if
specified), and then finally with `text` (again, if specified
and applicable).

In the check-out codepath, the blob content is first converted
with `text`, and then `ident` and fed to `filter`.


Merging branches with differing checkin/checkout attributes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you have added attributes to a file that cause the canonical
repository format for that file to change, such as adding a
clean/smudge filter or text/eol/ident attributes, merging anything
where the attribute is not in place would normally cause merge
conflicts.

To prevent these unnecessary merge conflicts, Git can be told to run a
virtual check-out and check-in of all three stages of a file when
resolving a three-way merge by setting the `merge.renormalize`
configuration variable.  This prevents changes caused by check-in
conversion from causing spurious merge conflicts when a converted file
is merged with an unconverted file.

As long as a "smudge->clean" results in the same output as a "clean"
even on files that are already smudged, this strategy will
automatically resolve all filter-related conflicts.  Filters that do
not act in this way may cause additional merge conflicts that must be
resolved manually.


Generating diff text
~~~~~~~~~~~~~~~~~~~~

`diff`
^^^^^^

The attribute `diff` affects how Git generates diffs for particular
files. It can tell Git whether to generate a textual patch for the path
or to treat the path as a binary file.  It can also affect what line is
shown on the hunk header `@@ -k,l +n,m @@` line, tell Git to use an
external command to generate the diff, or ask Git to convert binary
files to a text format before generating the diff.

Set::

	A path to which the `diff` attribute is set is treated
	as text, even when they contain byte values that
	normally never appear in text files, such as NUL.

Unset::

	A path to which the `diff` attribute is unset will
	generate `Binary files differ` (or a binary patch, if
	binary patches are enabled).

Unspecified::

	A path to which the `diff` attribute is unspecified
	first gets its contents inspected, and if it looks like
	text and is smaller than core.bigFileThreshold, it is treated
	as text. Otherwise it would generate `Binary files differ`.

String::

	Diff is shown using the specified diff driver.  Each driver may
	specify one or more options, as described in the following
	section. The options for the diff driver "foo" are defined
	by the configuration variables in the "diff.foo" section of the
	Git config file.


Defining an external diff driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The definition of a diff driver is done in `gitconfig`, not
`gitattributes` file, so strictly speaking this manual page is a
wrong place to talk about it.  However...

To define an external diff driver `jcdiff`, add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:

----------------------------------------------------------------
[diff "jcdiff"]
	command = j-c-diff
----------------------------------------------------------------

When Git needs to show you a diff for the path with `diff`
attribute set to `jcdiff`, it calls the command you specified
with the above configuration, i.e. `j-c-diff`, with 7
parameters, just like `GIT_EXTERNAL_DIFF` program is called.
See linkgit:git[1] for details.


Defining a custom hunk-header
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Each group of changes (called a "hunk") in the textual diff output
is prefixed with a line of the form:

	@@ -k,l +n,m @@ TEXT

This is called a 'hunk header'.  The "TEXT" portion is by default a line
that begins with an alphabet, an underscore or a dollar sign; this
matches what GNU 'diff -p' output uses.  This default selection however
is not suited for some contents, and you can use a customized pattern
to make a selection.

First, in .gitattributes, you would assign the `diff` attribute
for paths.

------------------------
*.tex	diff=tex
------------------------

Then, you would define a "diff.tex.xfuncname" configuration to
specify a regular expression that matches a line that you would
want to appear as the hunk header "TEXT". Add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:

------------------------
[diff "tex"]
	xfuncname = "^(\\\\(sub)*section\\{.*)$"
------------------------

Note.  A single level of backslashes are eaten by the
configuration file parser, so you would need to double the
backslashes; the pattern above picks a line that begins with a
backslash, and zero or more occurrences of `sub` followed by
`section` followed by open brace, to the end of line.

There are a few built-in patterns to make this easier, and `tex`
is one of them, so you do not have to write the above in your
configuration file (you still need to enable this with the
attribute mechanism, via `.gitattributes`).  The following built in
patterns are available:

- `ada` suitable for source code in the Ada language.

- `bibtex` suitable for files with BibTeX coded references.

- `cpp` suitable for source code in the C and C++ languages.

- `csharp` suitable for source code in the C# language.

- `css` suitable for cascading style sheets.

- `fortran` suitable for source code in the Fortran language.

- `fountain` suitable for Fountain documents.

- `golang` suitable for source code in the Go language.

- `html` suitable for HTML/XHTML documents.

- `java` suitable for source code in the Java language.

- `matlab` suitable for source code in the MATLAB language.

- `objc` suitable for source code in the Objective-C language.

- `pascal` suitable for source code in the Pascal/Delphi language.

- `perl` suitable for source code in the Perl language.

- `php` suitable for source code in the PHP language.

- `python` suitable for source code in the Python language.

- `ruby` suitable for source code in the Ruby language.

- `tex` suitable for source code for LaTeX documents.


Customizing word diff
^^^^^^^^^^^^^^^^^^^^^

You can customize the rules that `git diff --word-diff` uses to
split words in a line, by specifying an appropriate regular expression
in the "diff.*.wordRegex" configuration variable.  For example, in TeX
a backslash followed by a sequence of letters forms a command, but
several such commands can be run together without intervening
whitespace.  To separate them, use a regular expression in your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:

------------------------
[diff "tex"]
	wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"
------------------------

A built-in pattern is provided for all languages listed in the
previous section.


Performing text diffs of binary files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Sometimes it is desirable to see the diff of a text-converted
version of some binary files. For example, a word processor
document can be converted to an ASCII text representation, and
the diff of the text shown. Even though this conversion loses
some information, the resulting diff is useful for human
viewing (but cannot be applied directly).

The `textconv` config option is used to define a program for
performing such a conversion. The program should take a single
argument, the name of a file to convert, and produce the
resulting text on stdout.

For example, to show the diff of the exif information of a
file instead of the binary information (assuming you have the
exif tool installed), add the following section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file):

------------------------
[diff "jpg"]
	textconv = exif
------------------------

NOTE: The text conversion is generally a one-way conversion;
in this example, we lose the actual image contents and focus
just on the text data. This means that diffs generated by
textconv are _not_ suitable for applying. For this reason,
only `git diff` and the `git log` family of commands (i.e.,
log, whatchanged, show) will perform text conversion. `git
format-patch` will never generate this output. If you want to
send somebody a text-converted diff of a binary file (e.g.,
because it quickly conveys the changes you have made), you
should generate it separately and send it as a comment _in
addition to_ the usual binary diff that you might send.

Because text conversion can be slow, especially when doing a
large number of them with `git log -p`, Git provides a mechanism
to cache the output and use it in future diffs.  To enable
caching, set the "cachetextconv" variable in your diff driver's
config. For example:

------------------------
[diff "jpg"]
	textconv = exif
	cachetextconv = true
------------------------

This will cache the result of running "exif" on each blob
indefinitely. If you change the textconv config variable for a
diff driver, Git will automatically invalidate the cache entries
and re-run the textconv filter. If you want to invalidate the
cache manually (e.g., because your version of "exif" was updated
and now produces better output), you can remove the cache
manually with `git update-ref -d refs/notes/textconv/jpg` (where
"jpg" is the name of the diff driver, as in the example above).

Choosing textconv versus external diff
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you want to show differences between binary or specially-formatted
blobs in your repository, you can choose to use either an external diff
command, or to use textconv to convert them to a diff-able text format.
Which method you choose depends on your exact situation.

The advantage of using an external diff command is flexibility. You are
not bound to find line-oriented changes, nor is it necessary for the
output to resemble unified diff. You are free to locate and report
changes in the most appropriate way for your data format.

A textconv, by comparison, is much more limiting. You provide a
transformation of the data into a line-oriented text format, and Git
uses its regular diff tools to generate the output. There are several
advantages to choosing this method:

1. Ease of use. It is often much simpler to write a binary to text
   transformation than it is to perform your own diff. In many cases,
   existing programs can be used as textconv filters (e.g., exif,
   odt2txt).

2. Git diff features. By performing only the transformation step
   yourself, you can still utilize many of Git's diff features,
   including colorization, word-diff, and combined diffs for merges.

3. Caching. Textconv caching can speed up repeated diffs, such as those
   you might trigger by running `git log -p`.


Marking files as binary
^^^^^^^^^^^^^^^^^^^^^^^

Git usually guesses correctly whether a blob contains text or binary
data by examining the beginning of the contents. However, sometimes you
may want to override its decision, either because a blob contains binary
data later in the file, or because the content, while technically
composed of text characters, is opaque to a human reader. For example,
many postscript files contain only ASCII characters, but produce noisy
and meaningless diffs.

The simplest way to mark a file as binary is to unset the diff
attribute in the `.gitattributes` file:

------------------------
*.ps -diff
------------------------

This will cause Git to generate `Binary files differ` (or a binary
patch, if binary patches are enabled) instead of a regular diff.

However, one may also want to specify other diff driver attributes. For
example, you might want to use `textconv` to convert postscript files to
an ASCII representation for human viewing, but otherwise treat them as
binary files. You cannot specify both `-diff` and `diff=ps` attributes.
The solution is to use the `diff.*.binary` config option:

------------------------
[diff "ps"]
  textconv = ps2ascii
  binary = true
------------------------

Performing a three-way merge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`merge`
^^^^^^^

The attribute `merge` affects how three versions of a file are
merged when a file-level merge is necessary during `git merge`,
and other commands such as `git revert` and `git cherry-pick`.

Set::

	Built-in 3-way merge driver is used to merge the
	contents in a way similar to 'merge' command of `RCS`
	suite.  This is suitable for ordinary text files.

Unset::

	Take the version from the current branch as the
	tentative merge result, and declare that the merge has
	conflicts.  This is suitable for binary files that do
	not have a well-defined merge semantics.

Unspecified::

	By default, this uses the same built-in 3-way merge
	driver as is the case when the `merge` attribute is set.
	However, the `merge.default` configuration variable can name
	different merge driver to be used with paths for which the
	`merge` attribute is unspecified.

String::

	3-way merge is performed using the specified custom
	merge driver.  The built-in 3-way merge driver can be
	explicitly specified by asking for "text" driver; the
	built-in "take the current branch" driver can be
	requested with "binary".


Built-in merge drivers
^^^^^^^^^^^^^^^^^^^^^^

There are a few built-in low-level merge drivers defined that
can be asked for via the `merge` attribute.

text::

	Usual 3-way file level merge for text files.  Conflicted
	regions are marked with conflict markers `<<<<<<<`,
	`=======` and `>>>>>>>`.  The version from your branch
	appears before the `=======` marker, and the version
	from the merged branch appears after the `=======`
	marker.

binary::

	Keep the version from your branch in the work tree, but
	leave the path in the conflicted state for the user to
	sort out.

union::

	Run 3-way file level merge for text files, but take
	lines from both versions, instead of leaving conflict
	markers.  This tends to leave the added lines in the
	resulting file in random order and the user should
	verify the result. Do not use this if you do not
	understand the implications.


Defining a custom merge driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The definition of a merge driver is done in the `.git/config`
file, not in the `gitattributes` file, so strictly speaking this
manual page is a wrong place to talk about it.  However...

To define a custom merge driver `filfre`, add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:

----------------------------------------------------------------
[merge "filfre"]
	name = feel-free merge driver
	driver = filfre %O %A %B %L %P
	recursive = binary
----------------------------------------------------------------

The `merge.*.name` variable gives the driver a human-readable
name.

The `merge.*.driver` variable's value is used to construct a
command to run to merge ancestor's version (`%O`), current
version (`%A`) and the other branches' version (`%B`).  These
three tokens are replaced with the names of temporary files that
hold the contents of these versions when the command line is
built. Additionally, %L will be replaced with the conflict marker
size (see below).

The merge driver is expected to leave the result of the merge in
the file named with `%A` by overwriting it, and exit with zero
status if it managed to merge them cleanly, or non-zero if there
were conflicts.

The `merge.*.recursive` variable specifies what other merge
driver to use when the merge driver is called for an internal
merge between common ancestors, when there are more than one.
When left unspecified, the driver itself is used for both
internal merge and the final merge.

The merge driver can learn the pathname in which the merged result
will be stored via placeholder `%P`.


`conflict-marker-size`
^^^^^^^^^^^^^^^^^^^^^^

This attribute controls the length of conflict markers left in
the work tree file during a conflicted merge.  Only setting to
the value to a positive integer has any meaningful effect.

For example, this line in `.gitattributes` can be used to tell the merge
machinery to leave much longer (instead of the usual 7-character-long)
conflict markers when merging the file `Documentation/git-merge.txt`
results in a conflict.

------------------------
Documentation/git-merge.txt	conflict-marker-size=32
------------------------


Checking whitespace errors
~~~~~~~~~~~~~~~~~~~~~~~~~~

`whitespace`
^^^^^^^^^^^^

The `core.whitespace` configuration variable allows you to define what
'diff' and 'apply' should consider whitespace errors for all paths in
the project (See linkgit:git-config[1]).  This attribute gives you finer
control per path.

Set::

	Notice all types of potential whitespace errors known to Git.
	The tab width is taken from the value of the `core.whitespace`
	configuration variable.

Unset::

	Do not notice anything as error.

Unspecified::

	Use the value of the `core.whitespace` configuration variable to
	decide what to notice as error.

String::

	Specify a comma separate list of common whitespace problems to
	notice in the same format as the `core.whitespace` configuration
	variable.


Creating an archive
~~~~~~~~~~~~~~~~~~~

`export-ignore`
^^^^^^^^^^^^^^^

Files and directories with the attribute `export-ignore` won't be added to
archive files.

`export-subst`
^^^^^^^^^^^^^^

If the attribute `export-subst` is set for a file then Git will expand
several placeholders when adding this file to an archive.  The
expansion depends on the availability of a commit ID, i.e., if
linkgit:git-archive[1] has been given a tree instead of a commit or a
tag then no replacement will be done.  The placeholders are the same
as those for the option `--pretty=format:` of linkgit:git-log[1],
except that they need to be wrapped like this: `$Format:PLACEHOLDERS$`
in the file.  E.g. the string `$Format:%H$` will be replaced by the
commit hash.


Packing objects
~~~~~~~~~~~~~~~

`delta`
^^^^^^^

Delta compression will not be attempted for blobs for paths with the
attribute `delta` set to false.


Viewing files in GUI tools
~~~~~~~~~~~~~~~~~~~~~~~~~~

`encoding`
^^^^^^^^^^

The value of this attribute specifies the character encoding that should
be used by GUI tools (e.g. linkgit:gitk[1] and linkgit:git-gui[1]) to
display the contents of the relevant file. Note that due to performance
considerations linkgit:gitk[1] does not use this attribute unless you
manually enable per-file encodings in its options.

If this attribute is not set or has an invalid value, the value of the
`gui.encoding` configuration variable is used instead
(See linkgit:git-config[1]).


USING MACRO ATTRIBUTES
----------------------

You do not want any end-of-line conversions applied to, nor textual diffs
produced for, any binary file you track.  You would need to specify e.g.

------------
*.jpg -text -diff
------------

but that may become cumbersome, when you have many attributes.  Using
macro attributes, you can define an attribute that, when set, also
sets or unsets a number of other attributes at the same time.  The
system knows a built-in macro attribute, `binary`:

------------
*.jpg binary
------------

Setting the "binary" attribute also unsets the "text" and "diff"
attributes as above.  Note that macro attributes can only be "Set",
though setting one might have the effect of setting or unsetting other
attributes or even returning other attributes to the "Unspecified"
state.


DEFINING MACRO ATTRIBUTES
-------------------------

Custom macro attributes can be defined only in top-level gitattributes
files (`$GIT_DIR/info/attributes`, the `.gitattributes` file at the
top level of the working tree, or the global or system-wide
gitattributes files), not in `.gitattributes` files in working tree
subdirectories.  The built-in macro attribute "binary" is equivalent
to:

------------
[attr]binary -diff -merge -text
------------


EXAMPLES
--------

If you have these three `gitattributes` file:

----------------------------------------------------------------
(in $GIT_DIR/info/attributes)

a*	foo !bar -baz

(in .gitattributes)
abc	foo bar baz

(in t/.gitattributes)
ab*	merge=filfre
abc	-foo -bar
*.c	frotz
----------------------------------------------------------------

the attributes given to path `t/abc` are computed as follows:

1. By examining `t/.gitattributes` (which is in the same
   directory as the path in question), Git finds that the first
   line matches.  `merge` attribute is set.  It also finds that
   the second line matches, and attributes `foo` and `bar`
   are unset.

2. Then it examines `.gitattributes` (which is in the parent
   directory), and finds that the first line matches, but
   `t/.gitattributes` file already decided how `merge`, `foo`
   and `bar` attributes should be given to this path, so it
   leaves `foo` and `bar` unset.  Attribute `baz` is set.

3. Finally it examines `$GIT_DIR/info/attributes`.  This file
   is used to override the in-tree settings.  The first line is
   a match, and `foo` is set, `bar` is reverted to unspecified
   state, and `baz` is unset.

As the result, the attributes assignment to `t/abc` becomes:

----------------------------------------------------------------
foo	set to true
bar	unspecified
baz	set to false
merge	set to string value "filfre"
frotz	unspecified
----------------------------------------------------------------


SEE ALSO
--------
linkgit:git-check-attr[1].

GIT
---
Part of the linkgit:git[1] suite

debug log:

solving 92010b062 ...
found 92010b062 in https://80x24.org/mirrors/git.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).