-
Notifications
You must be signed in to change notification settings - Fork 0
/
Git-Book_9.html
2303 lines (2136 loc) · 110 KB
/
Git-Book_9.html
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
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.16">
<meta name="author" content="Valentin Haenel, Julius Plenz">
<title>Git Book — 8. Git Automation</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<link rel="stylesheet" href="style0.css" type="text/css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="style1.css" type="text/css">
<link rel="stylesheet" href="asciidoctor-chunker.css" type="text/css"></head>
<body class="book toc2 toc-left">
<div id="header">
<h1>Git: Distributed Version Control for Code and Documents</h1>
<div class="details">
<span id="author" class="author">Valentin Haenel</span><br>
<span id="author2" class="author">Julius Plenz</span><br>
<span id="revnumber">version 3.0</span>
<br><span id="revremark">Beta Preview</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="index.html">Title Page</a></li><li><a href="Git-Book_1.html">Preface</a>
<ul class="sectlevel2">
<li><a href="Git-Book_1.html#sec.reader">Who Is This Book Intended For?</a></li>
<li><a href="Git-Book_1.html#sec.structure">How to Read the Book?</a></li>
<li><a href="Git-Book_1.html#sec.conventions">Conventions</a></li>
<li><a href="Git-Book_1.html#sec.install-git-repo">Installation and “The Git-Repository”</a></li>
<li><a href="Git-Book_1.html#sec.docs">Documentation and Help</a></li>
<li><a href="Git-Book_1.html#sec.contact">Downloads and Contacts</a></li>
<li><a href="Git-Book_1.html#sec.acknowledgements">Acknowledgements</a></li>
<li><a href="Git-Book_1.html#sec.preface-2nd-edition">Preface to the 2nd Edition</a></li>
<li><a href="Git-Book_1.html#sec.preface-cc-edition">Preface to the Creative Commons Edition</a></li>
</ul>
</li>
<li><a href="Git-Book_2.html">1. Introduction and First Steps</a>
<ul class="sectlevel2">
<li><a href="Git-Book_2.html#sec.terminology">1.1. Basic Terminology</a></li>
<li><a href="Git-Book_2.html#sec.first-steps">1.2. First Steps with Git</a></li>
<li><a href="Git-Book_2.html#chap.git-config">1.3. Configuring Git</a></li>
</ul>
</li>
<li><a href="Git-Book_3.html">2. The Basics</a>
<ul class="sectlevel2">
<li><a href="Git-Book_3.html#sec.basics">2.1. Git Commands</a></li>
<li><a href="Git-Book_3.html#sec.object-model">2.2. The Object Model</a></li>
</ul>
</li>
<li><a href="Git-Book_4.html">3. Practical Version Control</a>
<ul class="sectlevel2">
<li><a href="Git-Book_4.html#sec.branches">3.1. References: Branches and Tags</a></li>
<li><a href="Git-Book_4.html#sec.undo">3.2. Restoring Versions</a></li>
<li><a href="Git-Book_4.html#sec.merge">3.3. Merging Branches</a></li>
<li><a href="Git-Book_4.html#sec.merge-conflicts">3.4. Resolving Merge Conflicts</a></li>
<li><a href="Git-Book_4.html#sec.cherry-pick">3.5. Taking over Individual Commits: Cherry Picking</a></li>
<li><a href="Git-Book_4.html#sec.visualization">3.6. Visualizing Repositories</a></li>
<li><a href="Git-Book_4.html#sec.reflog">3.7. Reflog</a></li>
</ul>
</li>
<li><a href="Git-Book_5.html">4. Advanced Concepts</a>
<ul class="sectlevel2">
<li><a href="Git-Book_5.html#sec.rebase">4.1. Moving commits — Rebase</a></li>
<li><a href="Git-Book_5.html#sec.rebase-i">4.2. Rewriting History — Interactive Rebase</a></li>
<li><a href="Git-Book_5.html#sec.blame">4.3. Who Made These Changes? — Git Blame</a></li>
<li><a href="Git-Book_5.html#sec.ignore">4.4. Ignoring Files</a></li>
<li><a href="Git-Book_5.html#sec.stash">4.5. Outsourcing Changes — Git Stash</a></li>
<li><a href="Git-Book_5.html#sec.notes">4.6. Annotating Commits — Git Notes</a></li>
<li><a href="Git-Book_5.html#sec.multi-root">4.7. Multiple Root Commits</a></li>
<li><a href="Git-Book_5.html#sec.bisect">4.8. Finding Regressions — Git Bisect</a></li>
</ul>
</li>
<li><a href="Git-Book_6.html">5. Distributed Git</a>
<ul class="sectlevel2">
<li><a href="Git-Book_6.html#sec.distributed-systems">5.1. How Does Distributed Version Control Work?</a></li>
<li><a href="Git-Book_6.html#sec.clone">5.2. Cloning Repositories</a></li>
<li><a href="Git-Book_6.html#sec.downloading-commits">5.3. Downloading Commits</a></li>
<li><a href="Git-Book_6.html#sec.uploading-commits">5.4. Uploading Commits: git push</a></li>
<li><a href="Git-Book_6.html#sec.remotes-check">5.5. Examining Remotes</a></li>
<li><a href="Git-Book_6.html#sec.multi-remote">5.6. Distributed Workflow with Multiple Remotes</a></li>
<li><a href="Git-Book_6.html#sec.managing-remotes">5.7. Managing Remotes</a></li>
<li><a href="Git-Book_6.html#sec.remote-tags">5.8. Exchanging Tags</a></li>
<li><a href="Git-Book_6.html#sec.patch-queue">5.9. Patches via E-mail</a></li>
<li><a href="Git-Book_6.html#sec.dictator">5.10. A Distributed, Hierarchical Workflow</a></li>
<li><a href="Git-Book_6.html#sec.subprojects">5.11. Managing Subprojects</a></li>
</ul>
</li>
<li><a href="Git-Book_7.html">6. Workflows</a>
<ul class="sectlevel2">
<li><a href="Git-Book_7.html#sec.workflows-user">6.1. User</a></li>
<li><a href="Git-Book_7.html#sec.branching-model">6.2. A Branching Model</a></li>
<li><a href="Git-Book_7.html#sec.releases-management">6.3. Release Management</a></li>
</ul>
</li>
<li><a href="Git-Book_8.html">7. Git Servers</a>
<ul class="sectlevel2">
<li><a href="Git-Book_8.html#sec.server">7.1. Hosting a Git Server</a></li>
<li><a href="Git-Book_8.html#sec.gitolite">7.2. Gitolite: Simple Git Hosting</a></li>
<li><a href="Git-Book_8.html#sec.git-daemon">7.3. Git Daemon: Anonymous Read-Only Access</a></li>
<li><a href="Git-Book_8.html#sec.gitweb">7.4. Gitweb: The Integrated Web Frontend</a></li>
<li><a href="Git-Book_8.html#sec.cgit">7.5. CGit — CGI for Git</a></li>
</ul>
</li>
<li class="current"><a href="Git-Book_9.html">8. Git Automation</a>
<ul class="sectlevel2">
<li class="current"><a href="Git-Book_9.html#sec.attributes">8.1. Git Attributes — Treating Files Separately</a></li>
<li class="current"><a href="Git-Book_9.html#sec.hooks">8.2. Hooks</a></li>
<li class="current"><a href="Git-Book_9.html#sec.scripting">8.3. Writing Your Own Git Commands</a></li>
<li class="current"><a href="Git-Book_9.html#sec.filter-branch">8.4. Rewriting Version History</a></li>
</ul>
</li>
<li><a href="Git-Book_10.html">9. Interacting with Other Version Control Systems</a>
<ul class="sectlevel2">
<li><a href="Git-Book_10.html#sec.subversion">9.1. Subversion</a></li>
<li><a href="Git-Book_10.html#sec.fast-import">9.2. Custom Importers</a></li>
</ul>
</li>
<li><a href="Git-Book_11.html">10. Shell Integration</a>
<ul class="sectlevel2">
<li><a href="Git-Book_11.html#sec.bash-integration">10.1. Git and the Bash</a></li>
<li><a href="Git-Book_11.html#sec.zsh-integration">10.2. Git and the Z-Shell</a></li>
</ul>
</li>
<li><a href="Git-Book_12.html">11. GitHub</a></li>
<li><a href="Git-Book_13.html">Appendix A: Installation</a>
<ul class="sectlevel2">
<li><a href="Git-Book_13.html#linux">A.1. Linux</a></li>
<li><a href="Git-Book_13.html#sec.osx">A.2. Mac OS X</a></li>
<li><a href="Git-Book_13.html#sec.windows">A.3. Windows</a></li>
</ul>
</li>
<li><a href="Git-Book_14.html">Appendix B: Repository Structure</a>
<ul class="sectlevel2">
<li><a href="Git-Book_14.html#sec.gc">B.1. Cleaning Up</a></li>
<li><a href="Git-Book_14.html#sec.gc-performance">B.2. Performance</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content"><div class="sect1">
<h2 id="ch.automation"><a class="anchor" href="Git-Book_9.html"></a>8. Git Automation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this chapter, we’ll introduce advanced techniques for automating Git.
In the first section about <em>Git attributes</em>, we’ll show you how to tell Git to treat certain files separately, for example, to call an external diff command on graphics.</p>
</div>
<div class="paragraph">
<p>We continue with <em>hooks</em> — small scripts that are executed when various git commands are called, for example to notify all developers via email when new commits arrive in the repository.</p>
</div>
<div class="paragraph">
<p>Then we’ll give a basic introduction to scripting with Git and show you useful <em>plumbing commands</em>.</p>
</div>
<div class="paragraph">
<p>Finally, we will introduce the powerful <code>filter-branch</code> command, which you can use to rewrite the project history on a large scale, for example to remove a file with a password from <em>all</em> commits.</p>
</div>
<div class="sect2">
<h3 id="sec.attributes"><a class="anchor" href="Git-Book_9.html#sec.attributes"></a>8.1. Git Attributes — Treating Files Separately</h3>
<div class="paragraph">
<p><em>Git attributes</em> allow you to assign specific properties to individual files or a group of files so that Git treats them with special care; examples would be forcing the end of lines or marking certain files as binary.</p>
</div>
<div class="paragraph">
<p>You can write the attributes either in the file <code>.gitattributes</code> or <code>.git/info/attributes</code>.
The latter is for a repository and is not managed by Git.
A <code>.gitattributes</code> file is usually checked in, so all developers use these attributes.
You can also store additional attribute definitions in subdirectories.</p>
</div>
<div class="paragraph">
<p>One line in this file has the format:</p>
</div>
<div class="listingblock">
<div class="content">
<pre><pattern> <attrib1> <attrib2> ...</pre>
</div>
</div>
<div class="paragraph">
<p>An example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>*.eps binary
*.tex -text
*.c filter=indent</pre>
</div>
</div>
<div class="paragraph">
<p>Usually attributes can be set (e.g. `binary`), canceled (<code>-text</code>) or set to a value (<code>filter=indent</code>).
The man page <code>gitattributes(5)</code> describes in detail how Git interprets the attributes.</p>
</div>
<div class="paragraph">
<p>A project that is developed in parallel on Windows and Unix machines suffers from the fact that the developers use different conventions for line endings.
This is due to the operating system:
Windows systems use a carriage return followed by a line feed (CRLF), while unixoid systems use only a line feed (LF).</p>
</div>
<div class="paragraph">
<p>By means of suitable git attributes you can determine an adequate policy — in this case the attributes <code>text</code> or <code>eol</code> are responsible.
The attribute <code>text</code> causes the line ends to be "normalized".
Whether a developer’s editor uses CRLF or just LF, Git will only store the version with LF in the blob.
If you set the attribute to <code>auto</code>, Git will only perform this normalization if the file also looks like text.</p>
</div>
<div class="paragraph">
<p>The <code>eol</code> attribute, on the other hand, determines what happens during a checkout.
Regardless of the user’s <code>core.eol</code> setting, you can specify e.g. CRLF for some files (because the format requires it).</p>
</div>
<div class="listingblock">
<div class="content">
<pre>*.txt text
*.csv eol=crlf</pre>
</div>
</div>
<div class="paragraph">
<p>With these attributes, <code>.txt</code> files are always saved internally with LF and checked out as CRLF if required (platform- or user-dependent).
CSV files on the other hand are checked out with CRLF on all platforms.
(Internally, Git will save all these blobs with simple LF extensions).</p>
</div>
<div class="sect3">
<h4 id="sec.smudge-clean"><a class="anchor" href="Git-Book_9.html#sec.smudge-clean"></a>8.1.1. Filter: Smudge and Clean</h4>
<div class="paragraph">
<p>Git offers a <em>filter</em> to "smudge" files after a checkout and to "clean" files again before a git add.</p>
</div>
<div class="paragraph">
<p>The filters do not get any arguments, but only the content of the blob on standard in.
The output of the program is used as new blob.</p>
</div>
<div class="paragraph">
<p>For each filter you have to define a Smudge and a Clean command.
If one of the definitions is missing or if the filter is <code>cat</code>, the blob is taken over unchanged.</p>
</div>
<div class="paragraph">
<p>Which filter is used for which type of files is defined by the git attribute <code>filter</code>.
For example, to automatically indent C files correctly before a commit, you can use the following filter definitions (instead of <code><indent></code>, any other name is possible):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>git config filter.<indent>.clean indent</strong>
$ <strong>git config filter.<indent>.smudge cat</strong>
$ <strong>echo '*.c filter=<indent>' > .git/info/attributes</strong></pre>
</div>
</div>
<div class="paragraph">
<p>To "clean up" a C file, Git now automatically calls the <code>indent</code> program that should be installed on standard systems.<sup class="footnote">[<a id="_footnoteref_106" class="footnote" href="#_footnotedef_106" title="View footnote.">106</a>]</sup></p>
</div>
</div>
<div class="sect3">
<h4 id="sec.smudge-clean-keywords"><a class="anchor" href="Git-Book_9.html#sec.smudge-clean-keywords"></a>8.1.2. Keywords in Files</h4>
<div class="paragraph">
<p>So in principle the well-known keyword expansions can be realized, so that e.g. <code>$Version$</code> becomes <code>$Version: v1.5.4-rc2$</code>.</p>
</div>
<div class="paragraph">
<p>You define the filters in your configuration and then equip corresponding files with this git attribute.
This works like this, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>git config filter.version.smudge \~/bin/git-version.smudge</strong>
$ <strong>git config filter.version.clean ~/bin/git-version.clean</strong>
$ <strong>echo '* filter=version' > .git/info/attributes</strong></pre>
</div>
</div>
<div class="paragraph">
<p>A filter that replaces or cleans up the <code>$Version$</code> keyword could be implemented as a Perl one-liner; first the Smudge filter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>#!/bin/sh
version=`git describe --tags`
exec perl -pe _s/$Version(:\s[^$]+)?$/$Version: _"$version"_$/g_</pre>
</div>
</div>
<div class="paragraph">
<p>And the Clean-Filter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>#!/usr/bin/perl -p
s/$Version: [^$]+$/$Version$/g</pre>
</div>
</div>
<div class="paragraph">
<p>It is important that repeated application of such a filter does not make uncontrolled changes in the file.
A double call to Smudge should be fixed by a single call to Clean.</p>
</div>
<div class="sect4">
<h5 id="sec.smudge-clean-dontuse"><a class="anchor" href="Git-Book_9.html#sec.smudge-clean-dontuse"></a>8.1.2.1. Restrictions</h5>
<div class="paragraph">
<p>The concept of filters in Git is intentionally kept simple and will not be expanded in future versions.
The filters receive <em>no</em> information about the context in which Git is currently located:
Is a checkout happening?
A merge?
A diff?
They only get the blob content.
So the filters should only perform <em>context-independent</em> manipulations.</p>
</div>
<div class="paragraph">
<p>At the time Smudge is called, the <code>HEAD</code> may not yet be up to date (the above filter would write an incorrect version number to the file during a <code>git checkout</code>, because it is called <em>before</em> the <code>HEAD</code> is moved).
So the filters are not very suitable for keyword expansion.</p>
</div>
<div class="paragraph">
<p>This may annoy users who have become accustomed to this feature in other version control systems.
However, there are no good arguments for such an expansion <em>within</em> a version control system.
The internal mechanisms Git uses to check if files have been modified are paralyzed (since they always have to go through the clean filter).
Also, because of the structure of Git repositories, you can "track" a blob through the commits or trees, so you can always tell if a file belongs to a commit by its contents if necessary.</p>
</div>
<div class="paragraph">
<p>So keyword expansion is only useful <em>outside</em> of Git.
This is not the responsibility of Git, but a <code>Makefile</code> target or script.
For example, a <code>make dist</code> can replace all occurrences of <code>VERSION</code> with the output of <code>git describe --tags</code>.
Git will display the files as "changed".
Once the files are distributed (e.g. as a tarball), you can clean up with <code>git reset --hard</code>.</p>
</div>
<div class="paragraph">
<p>Alternatively, the <code>export-subst</code> attribute ensures that an expansion of the form <code>$Format:<Pretty>$</code> is performed.
Where <code><Pretty></code> must be a format that is valid for <code>git log --pretty=format:<Pretty></code>, e.g. `%h` for the shortened commit hash sum.
Git will only expand these attributes if the file is packaged via <code>git archive</code> (see <a href="Git-Book_7.html#sec.release-create">Sec. 6.3.2, “Creating Releases”</a>).</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="sec.external-diff"><a class="anchor" href="Git-Book_9.html#sec.external-diff"></a>8.1.3. Own Diff Programs</h4>
<div class="paragraph">
<p>Git’s internal diff mechanism is very well suited for all types of plaintext.
But it fails with binaries - Git just tells you whether they differ or not.
However, if you have a project where you need to manage binary data, such as PDFs, OpenOffice documents, or images, it’s a good idea to define a special program that creates meaningful diffs for these files.</p>
</div>
<div class="paragraph">
<p>For example, there are <code>antiword</code> and <code>pdftotext</code> to convert Word documents and PDFs to plaintext.
There are analogous scripts for OpenOffice formats.
For images you can use commands from the ImageMagick suite (see also the example below).
If you manage statistical data, you can plot the changed recordsets side by side.
Depending on the nature of the data, there are usually adequate ways to visualize changes.</p>
</div>
<div class="paragraph">
<p>Such conversion processes are, of course, lossy:
You cannot use this diff output, for example to make meaningful changes to the files in a merge conflict.
But to get a quick overview of who changed what, such techniques are sufficient.</p>
</div>
<div class="sect4">
<h5 id="sec.external-diff-parameters"><a class="anchor" href="Git-Book_9.html#sec.external-diff-parameters"></a>8.1.3.1. API for External Diff Programs</h5>
<div class="paragraph">
<p>Git provides a simple API for custom diff filters.
A diff filter is always passed the following seven arguments:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>path (name of the file in the Git repository)</p>
</li>
<li>
<p>old version of the file</p>
</li>
<li>
<p>old SHA-1 ID of the blob</p>
</li>
<li>
<p>old Unix rights</p>
</li>
<li>
<p>new version of the file</p>
</li>
<li>
<p>new SHA-1 ID of the blob</p>
</li>
<li>
<p>new Unix rights</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>The arguments 2 and 5 may be temporary files, which will be deleted as soon as the diff program quits again, so you don’t have to care about cleaning up.</p>
</div>
<div class="paragraph">
<p>If one of the two files does not exist (newly added or deleted), then <code>/dev/null</code> is passed as file name.
The corresponding blob is then <code>00000</code>…, even if a file does not yet exist as a fixed object in the object database (i.e. only in the working tree or index).
The Diff command must be able to handle these cases accordingly.</p>
</div>
</div>
<div class="sect4">
<h5 id="sec.diff-config"><a class="anchor" href="Git-Book_9.html#sec.diff-config"></a>8.1.3.2. Configuring External Diffs</h5>
<div class="paragraph">
<p>There are two ways to call an external diff program.
The first method is temporary:
just set the environment variable <code>GIT_EXTERNAL_DIFF</code> to the path to your program before calling <code>git diff</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>GIT_EXTERNAL_DIFF=</pfad/zum/diff-kommando> git diff HEAD^</strong></pre>
</div>
</div>
<div class="paragraph">
<p>The other option is persistent, but requires some configuration.
First you define your own diff command <code><name></code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>git config diff.<name>.command </pfad/zum/diff-kommando></strong></pre>
</div>
</div>
<div class="paragraph">
<p>The command needs to be able to handle the above mentioned seven arguments.
Now you have to use the git-attribute <code>diff</code> to define, which diff-program is called.
To do this, write e.g. the following lines in the <code>.gitattributes</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>*.jpg diff=imgdiff
*.pdf diff=pdfdiff</pre>
</div>
</div>
<div class="paragraph">
<p>When you check the file in, other users must also have set corresponding commands for <code>imgdiff</code> or <code>pdfdiff</code>, otherwise they will see the regular output.
If you want to set this for one repository only, write this information to <code>.git/info/attributes</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="sec.diff-immages"><a class="anchor" href="Git-Book_9.html#sec.diff-immages"></a>8.1.3.3. Comparing Pictures</h5>
<div class="paragraph">
<p>A common use case are pictures:
What has changed between two versions of an image?
To visualize this is not always easy.
The tool <code>compare</code> from the ImageMagick suite marks the places that have changed for images of the same size.
You can also animate the two images one after the other and recognize by the "flickering" where the image has changed.</p>
</div>
<div class="paragraph">
<p>Instead, we want a program that compares the two images.
Between the two images a kind of "difference" is displayed:
All areas where changes have occurred are copied from the <em>new</em> image onto a white background.
So the diff shows which areas have been added.</p>
</div>
<div class="paragraph">
<p>Therefore we save the following script under <code>$HOME/bin/imgdiff</code>:<sup class="footnote">[<a id="_footnoteref_107" class="footnote" href="#_footnotedef_107" title="View footnote.">107</a>]</sup></p>
</div>
<div class="listingblock">
<div class="content">
<pre>#!/bin/sh
OLD="$2"
NEW="$5"
# "xc:none" ist "Nichts", entspricht einem fehlenden Bild
[ "$OLD" = "/dev/null" ] && OLD="xc:none"
[ "$NEW" = "/dev/null" ] && NEW="xc:none"
exec convert "$OLD" "$NEW" -alpha off \
\( -clone 0-1 -compose difference -composite -threshold 0 \) \
\( -clone 1-2 -compose copy_opacity -composite \
-compose over -background white -flatten \) \
-delete 2 -swap 1,2 +append \
-background white -flatten x:</pre>
</div>
</div>
<div class="paragraph">
<p>Finally, we need to configure the diff command and make sure it is used by an entry in the <code>.git/info/attributes</code> file.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>git config diff.imgdiff.command ~/bin/imgdiff</strong>
$ <strong>echo "*.gif diff=imgdiff" > .git/info/attributes</strong></pre>
</div>
</div>
<div class="paragraph">
<p>As an example we use the original versions of the Tux.<sup class="footnote">[<a id="_footnoteref_108" class="footnote" href="#_footnotedef_108" title="View footnote.">108</a>]</sup>
First we insert the black and white Tux:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>wget http://www.isc.tamu.edu/~lewing/linux/sit3-bw-tran.1.gif \</strong>
<strong>-Otux.gif</strong>
$ <strong>git add tux.gif && git commit -m "tux hinzugefügt"</strong></pre>
</div>
</div>
<div class="paragraph">
<p>It will be replaced by a colored version in the next commit:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ wget http://www.isc.tamu.edu/~lewing/linux/sit3-bw<strong>o</strong>-tran.1.gif \
-Otux.gif
$ <strong>git diff</strong></pre>
</div>
</div>
<div class="paragraph">
<p>The output of the <code>git diff</code> command is a window with the following content:
On the left the old version, on the right the new version, and in the middle a mask of those parts of the new image that are different from the old.</p>
</div>
<div id="fig.tux-diff" class="imageblock text-center">
<div class="content">
<img src="data:image/png;base64,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" alt="tux diff" width="70%">
</div>
<div class="title">Figure 46. The output of <code>git diff</code> with the custom diff program <code>imgdiff</code></div>
</div>
<div class="paragraph">
<p>The example with the Tux incl. manual can also be found in a repository at:
<a href="https://github.com/gitbuch/tux-diff-demo" class="bare">https://github.com/gitbuch/tux-diff-demo</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="sec.hooks"><a class="anchor" href="Git-Book_9.html#sec.hooks"></a>8.2. Hooks</h3>
<div class="paragraph">
<p>Hooks provide a mechanism to "hook" into important Git commands and perform your own actions.
Therefore, hooks are usually small shell scripts to perform automated tasks, such as sending emails as soon as new commits are uploaded, or checking for whitespace errors before a commit and issuing a warning if necessary.</p>
</div>
<div class="paragraph">
<p>For hooks to be executed by Git, they must be located in the <code>hooks/</code> directory in the Git directory, i.e. under <code>.git/hooks/</code> or under <code>hooks/</code> at the top level for bare repositories.
They must also be executable.</p>
</div>
<div class="paragraph">
<p>Git automatically installs sample hooks on a <code>git init</code>, but these have the extension <code><hook>.sample</code> and are therefore not executed without user intervention (renaming of files).</p>
</div>
<div class="paragraph">
<p>You can activate a supplied hook e.g. like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>mv .git/hooks/commit-msg.sample .git/hooks/commit-msg</strong></pre>
</div>
</div>
<div class="paragraph">
<p>Hooks come in two classes: those that are executed locally (checking commit messages or patches, performing actions after a merge or checkout, etc.), and those that are executed server-side when you publish changes via <code>git push</code>.<sup class="footnote">[<a id="_footnoteref_109" class="footnote" href="#_footnotedef_109" title="View footnote.">109</a>]</sup></p>
</div>
<div class="paragraph">
<p>Hooks whose name begins with <code>pre-</code> can often be used to decide whether or not to perform an action.
If a <code>pre</code>-hook does not end successfully (i.e. with a non-zero exit status), the action is aborted.
Technical documentation on how this works can be found in the <code>githooks(5)</code> man page.</p>
</div>
<div class="sect3">
<h4 id="sec.hooks-commit"><a class="anchor" href="Git-Book_9.html#sec.hooks-commit"></a>8.2.1. Commits</h4>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-commit</code></dt>
<dd>
<p>Is called before the commit message is queried.
If the hook terminates with a non-zero value, the commit process is aborted.
The hook installed by default checks whether a newly added file has non-ASCII characters in the file name and whether there are whitespace errors in the modified files.
With the <code>-n</code> or <code>--no-verify</code> option, <code>git commit</code> skips this hook.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>prepare-commit-msg</code></dt>
<dd>
<p>Will be executed right before the message is displayed in an editor.
Gets up to three parameters, the first of which is the file where the commit message is stored so that it can be edited.
For example, the hook can add lines automatically.
A non-zero exit status cancels the commit process.
However, this hook cannot be skipped and therefore should not duplicate or replace the functionality of <code>pre-commit</code>.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>commit-msg</code></dt>
<dd>
<p>Will be executed after the commit message is entered.
The only argument is the file where the message is stored, so that it can be modified (normalization).
This hook can be skipped by <code>-n</code> or <code>--no-verify</code>; if it does not terminate successfully, the commit process is aborted.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-commit</code></dt>
<dd>
<p>Called after a commit has been created.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>These hooks act only locally and are used to enforce certain policies regarding commits or commit messages.
The <code>pre-commit</code> hook is especially useful for this.
For example, some editors do not adequately indicate when there are spaces at the end of the line, or spaces contain spaces.
Again, this is annoying when other developers have to clean up whitespace in addition to regular changes.
This is where Git helps with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>git diff --cached --check</strong>
hooks.tex:82: trailing whitespace.
<strong>+</strong> auch noch Whitespace aufräumen müssen._</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>--check</code> option lets <code>git diff</code> check for such whitespace errors and will only exit successfully if the changes are error-free.
If you write this command in your <code>pre-commit</code> hook, you will always be warned if you want to check in whitespace errors.
If you are quite sure, you can simply suspend the hook temporarily with <code>git commit -n</code>.</p>
</div>
<div class="paragraph">
<p>Similarly, you can also store the "Check Syntax" command for a script language of your choice in this hook.
For example, the following block for Perl scripts:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>git diff --diff-filter=MA --cached --name-only |
while read file; do
if [ -f $file ] && [ $(head -n 1 $file) = "#!/usr/bin/perl" ]; then
perl -c $file || exit 1
fi
done
true</pre>
</div>
</div>
<div class="paragraph">
<p>The names of all files modified in the index (diff filter <code>modified</code> and <code>added</code>, see also <a href="Git-Book_9.html#sec.scripting-find-changes">Sec. 8.3.4, “Finding Changes”</a>) are passed to a subshell that checks per file whether the first line is a Perl script.
If so, the file is checked with <code>perl -c</code>.
If there is a syntax error in the file, the command will issue an appropriate error message, and <code>exit 1</code> will terminate the hook, so Git will abort the commit process before an editor is opened to enter the commit message.</p>
</div>
<div class="paragraph">
<p>The closing <code>true</code> is needed e.g. if a non-perl file was edited:
Then the if construct fails, the shell returns the return value of the last command, and although there is nothing to complain about, Git will not execute the commit.
With the line <code>true</code> the hook was successful if all passes of the <code>while</code> loop were successful.</p>
</div>
<div class="paragraph">
<p>The hook can of course be simplified by assuming that all Perl files are present as <code><name>.pl</code>.
Then the following code is sufficient:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>git ls-files -z -- _*.pl_ | xargs -z -n 1 perl -c</pre>
</div>
</div>
<div class="paragraph">
<p>Since you might want to check only the files managed by Git, a <code>git ls-files</code> is better than a simple <code>ls</code>, because that would also list untracked files ending in <code>.pl</code>.</p>
</div>
<div class="paragraph">
<p>Besides checking the syntax, you can of course also use Lint style programs that check the source code for "unsightly" or non portable constructs.</p>
</div>
<div class="paragraph">
<p>Such hooks are extremely useful to avoid accidentally checking in faulty code.
If warnings are inappropriate, you can always skip the hook <code>pre-commit</code> by using the <code>-n</code> option when committing.</p>
</div>
</div>
<div class="sect3">
<h4 id="sec.hooks-server"><a class="anchor" href="Git-Book_9.html#sec.hooks-server"></a>8.2.2. Server Side</h4>
<div class="paragraph">
<p>The following hooks are called on the receiver side of <code>git receive-pack</code> after the user enters <code>git push</code> in the local repository.</p>
</div>
<div class="paragraph">
<p>For a push operation, <code>git send-pack</code> creates <em>one</em> packfile on the local side (see also <a href="Git-Book_3.html#sec.od">Sec. 2.2.3, “The Object Database”</a>), which is received by <code>git receive-pack</code> on the recipient side.
Such a packfile contains the new values of one or more references as well as the commits required by the recipient repository to completely map the version history.
The two sides negotiate which commits these are in advance (similar to a merge base).</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-receive</code></dt>
<dd>
<p>The hook is called once and receives a list of changed references on standard input (see below for format).
If the hook does not complete successfully, <code>git receive-pack</code> refuses to accept it (the whole push operation fails).</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>update</code></dt>
<dd>
<p>Is called once <em>per changed reference</em> and gets three arguments: the old state of the reference, the proposed new one and the name of the reference.
If the hook does not end successfully, the update of the single reference is denied (in contrast to <code>pre-receive</code>, where only a whole packfile can be agreed or not).</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-receive</code></dt>
<dd>
<p>Similar to <code>pre-receive</code>, but is called only <em>after</em> the references have been changed (so it has no influence on whether the packfile is accepted or not).</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-update</code></dt>
<dd>
<p>After all references are changed, this hook is executed once and gets the names of all changed references as arguments.
But the hook is not told, on which state the references were before or are now.
(You can use <code>post-receive</code> for this.)
A typical use case is a call to <code>git update-server-info</code>, which is necessary if you want to provide a repository via HTTP.</p>
</dd>
</dl>
</div>
<div class="sect4">
<h5 id="sec.hooks-receive-format"><a class="anchor" href="Git-Book_9.html#sec.hooks-receive-format"></a>8.2.2.1. The Format of the Receive Hooks</h5>
<div class="paragraph">
<p>The <code>pre-receive</code> and <code>post-receive</code> hooks get an equivalent input to standard input.
The format is the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre><alte-sha1> <neue-sha1> <name-der-referenz></pre>
</div>
</div>
<div class="paragraph">
<p>This can look like this, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>0000000...0000000 ca0e8cf...12b14dc refs/heads/newbranch
ca0e8cf...12b14dc 0000000...0000000 refs/heads/oldbranch
6618257...93afb8d 62dec1c...ac5373b refs/heads/master</pre>
</div>
</div>
<div class="paragraph">
<p>A SHA-1 sum of all zeros means "not present".
So the first line describes a reference that was not present before, while the second line means the deletion of a reference.
The third line represents a regular update.</p>
</div>
<div class="paragraph">
<p>You can easily read the references with the following loop:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>while read old new ref; do
# ...
done</pre>
</div>
</div>
<div class="paragraph">
<p>In <code>old</code> and <code>new</code> then the SHA-1 sums are stored, while <code>ref</code> contains the name of the reference.
A <code>git log $old..$new</code> would list all new commits.
The default output is forwarded to <code>git send-pack</code> on the page where <code>git push</code> was entered.
So you can forward any error messages or reports directly to the user.</p>
</div>
</div>
<div class="sect4">
<h5 id="sec.hooks-email"><a class="anchor" href="Git-Book_9.html#sec.hooks-email"></a>8.2.2.2. Sending E-Mails</h5>
<div class="paragraph">
<p>A practical use of the <code>post-receive</code> hook is to send out emails as soon as new commits are available in the repository.
You can program this yourself, of course, but there is a ready-made script that comes with Git.
You can find it in the Git source directory under <code>contrib/hooks/post-receive-email</code>, and some distributions, such as Debian, also install it along with Git to <code>/usr/share/doc/git/contrib/hooks/post-receive-email</code>.</p>
</div>
<div class="paragraph">
<p>Once you have copied the hook into the <code>hooks/</code> subdirectory of your bare repository and made it executable, you can adjust the configuration accordingly:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ <strong>less config</strong>
...
[hooks]
mailinglist = "Autor Eins <[email protected]>, [email protected]"
envelopesender = "[email protected]"
emailprefix = "[project] "</pre>
</div>
</div>
<div class="paragraph">
<p>This means that for each push operation per reference, a mail is sent with a summary of the new commits.
The mail goes to all recipients defined in <code>hooks.mailinglist</code> and comes from <code>hooks.envelopesender</code>.
The subject line is prefixed with the <code>hooks.emailprefix</code>, so that the mail can be sorted away more easily.
More options are documented in the comments of the hooks.</p>
</div>
</div>
<div class="sect4">
<h5 id="sec.hooks-update"><a class="anchor" href="Git-Book_9.html#sec.hooks-update"></a>8.2.2.3. The Update Hook</h5>
<div class="paragraph">
<p>The <code>update</code> hook is called for each reference individually.
It is therefore particularly well suited to implement a kind of "access control" to certain branches.</p>
</div>
<div class="paragraph">
<p>In fact, the <code>update</code> hook is used by Gitolite (see <a href="Git-Book_8.html#sec.gitolite">Sec. 7.2, “Gitolite: Simple Git Hosting”</a>) to decide whether a branch may be modified or not.
Gitolite implements the hook as a Perl script that checks whether the appropriate permission is present and terminates with a zero or non-zero return value accordingly.</p>
</div>
</div>
<div class="sect4">
<h5 id="sec.hooks-deploy"><a class="anchor" href="Git-Book_9.html#sec.hooks-deploy"></a>8.2.2.4. Deployment via Hooks</h5>
<div class="paragraph">
<p>Git is a version control system and knows nothing about deployment processes.
However, you can use the update hook to implement a simple deployment procedure - e.g. for web applications.</p>
</div>
<div class="paragraph">
<p>The following <code>update</code> hook will, if the <code>master</code> branch has changed, replicate the changes to <code>/var/www/www.example.com</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[ "$3" = "refs/heads/master" ] || exit 0
env GIT_WORK_TREE=/var/www/www.example.com git checkout -f</pre>
</div>
</div>
<div class="paragraph">
<p>So as soon as you upload new commits via <code>git push</code> to the server’s master branch, this hook will automatically update the web presence.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="sec.hooks-am"><a class="anchor" href="Git-Book_9.html#sec.hooks-am"></a>8.2.3. Applying Patches</h4>
<div class="paragraph">
<p>The following hooks are each called by <code>git am</code> when one or more patches are applied.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>applypatch-msg</code></dt>
<dd>
<p>Is called before a Patch is applied.
The hook receives as its only parameter the file where the commit message of the patch is stored.
The hook can change the message if necessary.
A non-zero exit status causes <code>git am</code> not to accept the patch.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-applypatch</code></dt>
<dd>
<p>Called after a patch has been applied, but before the change is committed.
A non-zero exit status causes <code>git am</code> not to accept the patch.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-applypatch</code></dt>
<dd>
<p>Is called after a patch has been applied.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The hooks installed by default execute the corresponding commit hooks <code>commit-msg</code> and <code>pre-commit</code>, if enabled.</p>
</div>
</div>
<div class="sect3">
<h4 id="sec.hooks-misc"><a class="anchor" href="Git-Book_9.html#sec.hooks-misc"></a>8.2.4. Other Hooks</h4>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-rebase</code></dt>
<dd>
<p>Is executed before a rebase process starts.
Gets as arguments the references that are also passed to the rebase command (e.g. for the <code>git rebase master topic</code> command, the hook gets the arguments <code>master</code> and <code>topic</code>).
Based on the exit status <code>git rebase</code> decides whether the rebase process is executed or not.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-push</code></dt>
<dd>
<p>Is executed before a push operation starts.
Receives on standard input lines of the form <code><locale-ref></code>␣`<locale-sha1>`␣`<remote-ref>`␣`<remote-sha1>`.
If the hook does not terminate successfully, the push process is aborted.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-rewrite</code></dt>
<dd>
<p>Is called by commands that rewrite commits (currently only <code>git commit --amend</code> and <code>git rebase</code>).
Receives a list in the format <code><old-sha1></code>␣`<new-sha1>` on standard input.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-checkout</code></dt>
<dd>
<p>Is called after a checkout.
The first two parameters are the old and new reference to which <code>HEAD</code> points.
The third parameter is a flag that indicates whether a branch has been changed (<code>1</code>) or individual files have been checked out (<code>0</code>).</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>post-merge</code></dt>
<dd>
<p>Will be executed if a merge was successfully completed.
The hook gets a <code>1</code> as argument if the merge was a so called squash-merge, i.e. a merge that did not create a commit but only processed the files in the working tree.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>pre-auto-gc</code></dt>
<dd>
<p>Is called before <code>git gc --auto</code> is executed.
Prevents execution of the automatic garbage collection if the return value is not zero.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>You can use the <code>post-checkout</code> and <code>post-commit</code> hooks to teach Git "real" file permissions.
This is because a blob object does not accurately reflect the contents of a file and its access rights.
Instead, Git only knows "executable" or "non-executable".<sup class="footnote">[<a id="_footnoteref_110" class="footnote" href="#_footnotedef_110" title="View footnote.">110</a>]</sup></p>
</div>
<div class="paragraph">
<p>The script stored in the git source directory under <code>contrib/hooks/setgitperms.perl</code> provides a ready-made solution that you can integrate into the above hooks.
The script stores the real access rights in a <code>.gitmeta</code> file.
If you do the read-in (option <code>-r</code>) in the <code>pre-commit</code> hook and give the hooks <code>post-checkout</code> and <code>post-merge</code> the command to write permissions (option <code>-w</code>), the permissions of your files should now be persistent.
See the comments in the file for the exact commands.</p>
</div>
<div class="paragraph">
<p>The access rights are of course only stable between checkouts - unless you check in the <code>.gitmeta</code> file and force the use of the hooks, clones of this repository will of course only get the "basic" access rights.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="sec.scripting"><a class="anchor" href="Git-Book_9.html#sec.scripting"></a>8.3. Writing Your Own Git Commands</h3>
<div class="paragraph">
<p>Git follows the Unix philosophy of "one tool, one job" with its division into subcommands.
It also divides the subcommands into two categories: <em>Porcelain</em> and <em>Plumbing</em>.</p>
</div>
<div class="paragraph">
<p>Porcelain refers to the "good porcelain" that is taken out of the cupboard for the end user: a tidy user interface and human-readable output.
Plumbing commands, on the other hand, are mainly used for "plumbing work" in scripts and have a machine-readable output (usually line by line with unique separators).</p>
</div>
<div class="paragraph">
<p>In fact, a substantial part of the Porcelain commands is implemented as shell script.
They use the various plumbing commands internally, but present a comprehensible interface to the outside.
The commands <code>rebase</code>, <code>am</code>, <code>bisect</code> and <code>stash</code> are just a few examples.</p>
</div>
<div class="paragraph">
<p>It is therefore useful and easy to write your own shell scripts to automate frequently occurring tasks in your workflow.
These could be scripts that control the release process of the software, create automatic changelogs or other operations tailored to the project.</p>
</div>
<div class="paragraph">
<p>Writing your own git command is very easy:
You just have to place an executable file in a directory of your <code>$PATH</code> (e.g. in <code>~/bin</code>) whose name starts with <code>git-</code>.
If you type <code>git <command></code> and <code><command></code> is neither an alias nor a known command, Git will simply try to run <code>git-<command></code>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tbody><tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Even if you can write scripts in any language you like, we recommend using shell scripts:
Not only are they easier to understand for outsiders, but above all, the typical operations used to combine Git commands - calling programs, redirecting output - are "intuitively" possible with the shell and do not require any complicated constructs, such as <code>qx()</code> in Perl or <code>os.popen()</code> in Python.</p>
</div>
<div class="paragraph">
<p>When writing shell scripts, please pay attention to POSIX compatibility!<sup class="footnote">[<a id="_footnoteref_111" class="footnote" href="#_footnotedef_111" title="View footnote.">111</a>]</sup>
This includes in particular not using "bashisms" like <code>[[ … ]]</code> (the POSIX equivalent is <code>[ … ]</code>).
If your script does not run without problems with Dash<sup class="footnote">[<a id="_footnoteref_112" class="footnote" href="#_footnotedef_112" title="View footnote.">112</a>]</sup>, you should explicitly specify the shell used in the shebang line, e.g. via <code>#!/bin/bash</code>.</p>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p>All scripts presented in the following section can also be found online, in the script collection for this book.<sup class="footnote">[<a id="_footnoteref_113" class="footnote" href="#_footnotedef_113" title="View footnote.">113</a>]</sup></p>
</div>
<div class="sect3">
<h4 id="sec.scripting-init"><a class="anchor" href="Git-Book_9.html#sec.scripting-init"></a>8.3.1. Initialization</h4>
<div class="paragraph">
<p>Typically, you want to ensure that your script is executed in a repository.
For necessary initialization tasks, Git offers the <code>git-sh-setup</code>.
You should include this shell script directly after the shebang line using <code>.</code> (known as <code>source</code> in interactive shells):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>#!/bin/sh
. $(git --exec-path)/git-sh-setup</pre>
</div>
</div>
<div class="paragraph">
<p>Unless Git can detect a repository, <code>git-sh-setup</code> will abort.
Also, the script will abort if it is not running at the top level in a repository.
Your script will not be executed and an error message will be displayed.
You can work around this behavior by setting the <code>NONGIT_OK</code> or <code>SUBDIRECTORY_OK</code> variable before the call.</p>
</div>
<div class="paragraph">
<p>Beside this initialization mechanism there are some functions available, which do frequently occurring tasks.
Below is an overview of the most important ones:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>cd_to_toplevel</code></dt>
<dd>
<p>Switches to the top level of the Git repository.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>say</code></dt>
<dd>
<p>Outputs the arguments, unless <code>GIT_QUIET</code> is set.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>git_editor</code></dt>
<dd>
<p>Opens the editor set for Git on the specified files.
It’s better to use this function than "blind" `$EDITOR`.
Git also uses this as a fallback.</p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>git_pager</code></dt>
<dd>
<p>Opens the pager defined for Git.</p>
</dd>
</dl>
</div>
<div class="dlist">