This Git documentation is based on Git 2.53. The up to date Git reference can be found on https://git-scm.com/docs/
This manual describes the convention used throughout Git CLI.
Many commands take revisions (most often "commits", but sometimes "tree-ish", depending on the context and command) and paths as their arguments. Here are the rules:
Because -- disambiguates revisions and paths in some commands, it cannot be used for those commands to separate options and revisions. You can use --end-of-options for this (it also works for commands that do not distinguish between revisions in paths, in which case it is simply an alias for --).
When writing a script that is expected to handle random user-input, it is a good practice to make it explicit which arguments are which by placing disambiguating -- at appropriate places.
Many commands allow wildcards in paths, but you need to protect them from getting globbed by the shell. These two mean different things:
$ git restore *.c $ git restore \*.c
The former lets your shell expand the fileglob, and you are asking the dot-C files in your working tree to be overwritten with the version in the index. The latter passes the *.c to Git, and you are asking the paths in the index that match the pattern to be checked out to your working tree. After running git add hello.c; rm hello.c, you will not see hello.c in your working tree with the former, but with the latter you will.
Here are the rules regarding the "flags" that you should follow when you are scripting Git:
From the Git 1.5.4 series and further, many Git commands (not all of them at the time of the writing though) come with an enhanced option parser.
Here is a list of the facilities provided by this option parser.
Commands which have the enhanced option parser activated all understand a couple of magic command-line options:
gives a pretty printed usage of the command.
$ git describe -h
usage: git describe [<options>] <commit-ish>*
or: git describe [<options>] --dirty
--contains find the tag that comes after the commit
--debug debug search strategy on stderr
--all use any ref
--tags use any tag, even unannotated
--long always use long format
--abbrev[=<n>] use <n> digits to display SHA-1sNote that some subcommand (e.g. git grep) may behave differently when there are things on the command line other than -h, but git subcmd -h without anything else on the command line is meant to consistently give the usage.
Options with long option names can be negated by prefixing --no-. For example, git branch has the option --track which is on by default. You can use --no-track to override that behaviour. The same goes for --color and --no-color.
When there is a configuration variable or an environment variable that tweak the behaviour of an aspect of a Git command, and also a command line option that tweaks the same, the command line option overrides what the configuration and/or environment variable say.
For example, the user.name configuration variable is used to specify the human-readable name used by the git commit command to record the author and the committer name in a newly created commit. The GIT_AUTHOR_NAME environment variable, if set, takes precedence when deciding what author name to record. The --author=<author> command line option of the git commit command, when given, takes precedence over these two sources of information.
Commands that support the enhanced option parser allow you to aggregate short options. This means that you can for example use git rm -rf or git clean -fdx.
Commands that support the enhanced option parser accepts unique prefix of a long option as if it is fully spelled out, but use this with a caution. For example, git commit --amen behaves as if you typed git commit --amend, but that is true only until a later version of Git introduces another option that shares the same prefix, e.g. git commit --amenity option.
You can write the mandatory option parameter to an option as a separate word on the command line. That means that all the following uses work:
$ git foo --long-opt=Arg $ git foo --long-opt Arg $ git foo -oArg $ git foo -o Arg
However, this is NOT allowed for switches with an optional value, where the stuck form must be used:
$ git describe --abbrev HEAD # correct $ git describe --abbrev=10 HEAD # correct $ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT
Options that take a filename allow a prefix :(optional). For example:
git commit -F :(optional)COMMIT_EDITMSG # if COMMIT_EDITMSG does not exist, the above is equivalent to git commit
Like with configuration values, if the named file is missing Git behaves as if the option was not given at all. See "Values" in the section called “git-config(1)”.
Many commands that can work on files in the working tree and/or in the index can take --cached and/or --index options. Sometimes people incorrectly think that, because the index was originally called cache, these two are synonyms. They are not -- these two options mean very different things.
git apply command can be used with --cached and --index (but not at the same time). Usually the command only affects the files in the working tree, but with --index, it patches both the files and their index entries, and with --cached, it modifies only the index entries.
See also https://lore.kernel.org/git/7v64clg5u9.fsf@assigned-by-dhcp.cox.net/ and https://lore.kernel.org/git/7vy7ej9g38.fsf@gitster.siamese.dyndns.org/ for further information.
Some other commands that also work on files in the working tree and/or in the index can take --staged and/or --worktree.
Part of the the section called “git(1)” suite
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:
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 the section called “gitignore(5)”), with a few exceptions:
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 the section called “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 !.
builtin_* is a reserved namespace for builtin attribute values. Any user defined attributes under this namespace will be ignored and trigger a warning.
This attribute is for filtering files by their file bit modes (40000, 120000, 160000, 100755, 100644). e.g. :(attr:builtin_objectmode=160000). You may also check these values with git check-attr builtin_objectmode -- <file>. If the object is not in the index git check-attr --cached will return unspecified.
Certain operations by Git can be influenced by assigning particular attributes to a path. Currently, the following operations are attributes-aware.
These attributes affect how the contents stored in the repository are copied to the working tree files when commands such as git switch, 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.
This attribute marks the path as a text file, which enables end-of-line conversion: When a matching file is added to the index, the file's line endings are normalized to LF in the index. Conversely, when the file is copied from the index to the working directory, its line endings may be converted from LF to CRLF depending on the eol attribute, the Git config, and the platform (see explanation of eol below).
Any other value causes Git to act as if text has been left unspecified.
This attribute marks a path to use a specific line-ending style in the working tree when it is checked out. It has effect only if text or text=auto is set (see above), but specifying eol automatically sets text if text was left unspecified.
For backwards compatibility, the crlf attribute is interpreted as follows:
crlf text -crlf -text crlf=input eol=lf
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 = trueThis 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
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 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 re-encodes 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 re-encoded 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.
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 (use UTF-16LE-BOM instead of UTF-16LE if you want UTF-16 little endian with BOM). 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
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.
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 = catFor 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 ...
requiredSequence "%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 %fNote 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.
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 Documentation/technical/long-running-process-protocol.adoc).
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 supported, 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.
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!
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 the section called “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.
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.
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 each file that needs a three-way content 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.
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.
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-diffWhen 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 the section called “git(1)” for details.
If the program is able to ignore certain changes (similar to git diff --ignore-space-change), then also set the option trustExitCode to true. It is then expected to return exit code 1 if it finds significant changes and 0 if it doesn't.
The diff algorithm can be set through the diff.algorithm config key, but sometimes it may be helpful to set the diff algorithm per path. For example, one may want to use the minimal diff algorithm for .json files, and the histogram for .c files, and so on without having to pass in the algorithm through the command line each time.
First, in .gitattributes, assign the diff attribute for paths.
*.json diff=<name>
Then, define a "diff.<name>.algorithm" configuration to specify the diff algorithm, choosing from myers, patience, minimal, or histogram.
[diff "<name>"] algorithm = histogram
This diff algorithm applies to user facing diff output like git-diff(1), git-show(1) and is used for the --stat output as well. The merge machinery will not use the diff algorithm set through this method.
If diff.<name>.command is defined for path with the diff=<name> attribute, it is executed as an external diff driver (see above), and adding diff.<name>.algorithm has no effect, as the algorithm is not passed to the external diff driver.
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:
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.
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 = exifThe 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 = trueThis 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).
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:
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
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.
There are a few built-in low-level merge drivers defined that can be asked for via the merge attribute.
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 = binaryThe 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 common 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. When the driver crashes (e.g. killed by SEGV), it is expected to exit with non-zero status that are higher than 128, and in such a case, the merge results in a failure (which is different from producing a conflict).
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. The conflict labels to be used for the common ancestor, local head and other head can be passed by using %S, %X and %Y respectively.
This attribute controls the length of conflict markers left in the work tree file during a conflicted merge. Only a positive integer has a 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.adoc results in a conflict.
Documentation/git-merge.adoc conflict-marker-size=32
The core.whitespace configuration variable allows you to define what diff and apply should consider whitespace errors for all paths in the project (See the section called “git-config(1)”). This attribute gives you finer control per path.
Files and directories with the attribute export-ignore won't be added to archive files.
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 the section called “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 the section called “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. However, only one %(describe) placeholder is expanded per archive to avoid denial-of-service attacks.
The value of this attribute specifies the character encoding that should be used by GUI tools (e.g. the section called “gitk(1)” and the section called “git-gui(1)”) to display the contents of the relevant file. Note that due to performance considerations the section called “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 the section called “git-config(1)”).
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.
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
Git does not follow symbolic links when accessing a .gitattributes file in the working tree. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem.
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:
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
Part of the the section called “git(1)” suite
git config credential.https://example.com.username myusername git config credential.helper "$helper $options"
Git will sometimes need credentials from the user in order to perform operations; for example, it may need to ask for a username and password in order to access a remote repository over HTTP. Some remotes accept a personal access token or OAuth access token as a password. This manual describes the mechanisms Git uses to request these credentials, as well as some features to avoid inputting these credentials repeatedly.
Without any credential helpers defined, Git will try the following strategies to ask the user for usernames and passwords:
It can be cumbersome to input the same credentials over and over. Git provides two methods to reduce this annoyance:
The first is simple and appropriate if you do not have secure storage available for a password. It is generally configured by adding this to your config:
[credential "https://example.com"]
username = meCredential helpers, on the other hand, are external programs from which Git can request both usernames and passwords; they typically interface with secure storage provided by the OS or other programs. Alternatively, a credential-generating helper might generate credentials for certain servers via some API.
To use a helper, you must first select one to use (see below for a list).
You may also have third-party helpers installed; search for credential-* in the output of git help -a, and consult the documentation of individual helpers. Once you have selected a helper, you can tell Git to use it by putting its name into the credential.helper variable.
Find a helper.
$ git help -a | grep credential- credential-foo
Read its description.
$ git help credential-foo
Tell Git to use it.
$ git config --global credential.helper foo
Git currently includes the following helpers:
Popular helpers with secure persistent storage include:
The community maintains a comprehensive list of Git credential helpers at https://git-scm.com/doc/credential-helpers.
An alternative to inputting passwords or personal access tokens is to use an OAuth credential helper. Initial authentication opens a browser window to the host. Subsequent authentication happens in the background. Many popular Git hosts support OAuth.
Popular helpers with OAuth support include:
Git considers each credential to have a context defined by a URL. This context is used to look up context-specific configuration, and is passed to any helpers, which may use it as an index into secure storage.
For instance, imagine we are accessing https://example.com/foo.git. When Git looks into a config file to see if a section matches this context, it will consider the two a match if the context is a more-specific subset of the pattern in the config file. For example, if you have this in your config file:
[credential "https://example.com"]
username = foothen we will match: both protocols are the same and both hosts are the same. However, this context would not match:
[credential "https://kernel.org"]
username = foobecause the hostnames differ. Nor would it match foo.example.com; Git compares hostnames exactly, without considering whether two hosts are part of the same domain. Likewise, a config entry for http://example.com would not match: Git compares the protocols exactly. However, you may use wildcards in the domain name and other pattern matching techniques as with the http.<URL>.* options.
If the "pattern" URL does include a path component, then this must match as a prefix path: the context https://example.com/bar will match a config entry for https://example.com/bar/baz.git but will not match a config entry for https://example.com/other/repo.git or https://example.com/barry/repo.git (even though it is a string prefix).
Options for a credential context can be configured either in credential.* (which applies to all credentials), or credential.<URL>.*, where <URL> matches the context as described above.
The following options are available in either location:
The name of an external credential helper, and any associated options. If the helper name is not an absolute path, then the string git credential- is prepended. The resulting string is executed by the shell (so, for example, setting this to foo --option=bar will execute git credential-foo --option=bar via the shell. See the manual of specific helpers for examples of their use.
If there are multiple instances of the credential.helper configuration variable, each helper will be tried in turn, and may provide a username, password, or nothing. Once Git has acquired both a username and a non-expired password, no more helpers will be tried.
If credential.helper is configured to the empty string, this resets the helper list to empty (so you may override a helper set by a lower-priority config file by configuring the empty-string helper, followed by whatever set of helpers you would like).
You can write your own custom helpers to interface with any system in which you keep credentials.
Credential helpers are programs executed by Git to fetch or save credentials from and to long-term storage (where "long-term" is simply longer than a single Git process; e.g., credentials may be stored in-memory for a few minutes, or indefinitely on disk).
Each helper is specified by a single string in the configuration variable credential.helper (and others, see the section called “git-config(1)”). The string is transformed by Git into a command to be executed using these rules:
The resulting command then has an "operation" argument appended to it (see below for details), and the result is executed by the shell.
Here are some example specifications:
# run "git credential-foo"
[credential]
helper = foo
# same as above, but pass an argument to the helper
[credential]
helper = "foo --bar=baz"
# the arguments are parsed by the shell, so use shell
# quoting if necessary
[credential]
helper = "foo --bar='whitespace arg'"
# store helper (discouraged) with custom location for the db file;
# use `--file ~/.git-secret.txt`, rather than `--file=~/.git-secret.txt`,
# to allow the shell to expand tilde to the home directory.
[credential]
helper = "store --file ~/.git-secret.txt"
# you can also use an absolute path, which will not use the git wrapper
[credential]
helper = "/path/to/my/helper --with-arguments"
# or you can specify your own shell snippet
[credential "https://example.com"]
username = your_user
helper = "!f() { test \"$1\" = get && echo \"password=$(cat $HOME/.secret)\"; }; f"Generally speaking, rule (3) above is the simplest for users to specify. Authors of credential helpers should make an effort to assist their users by naming their program "git-credential-$NAME", and putting it in the $PATH or $GIT_EXEC_PATH during installation, which will allow a user to enable it with git config credential.helper $NAME.
When a helper is executed, it will have one "operation" argument appended to its command line, which is one of:
The details of the credential will be provided on the helper's stdin stream. The exact format is the same as the input/output format of the git credential plumbing command (see the section INPUT/OUTPUT FORMAT in the section called “git-credential(1)” for a detailed specification).
For a get operation, the helper should produce a list of attributes on stdout in the same format (see the section called “git-credential(1)” for common attributes). A helper is free to produce a subset, or even no values at all if it has nothing useful to provide. Any provided attributes will overwrite those already known about by Git's credential subsystem. Unrecognised attributes are silently discarded.
While it is possible to override all attributes, well behaving helpers should refrain from doing so for any attribute other than username and password.
If a helper outputs a quit attribute with a value of true or 1, no further helpers will be consulted, nor will the user be prompted (if no credential has been provided, the operation will then fail).
Similarly, no more helpers will be consulted once both username and password had been provided.
For a store or erase operation, the helper's output is ignored.
If a helper fails to perform the requested operation or needs to notify the user of a potential issue, it may write to stderr.
If it does not support the requested operation (e.g., a read-only store or generator), it should silently ignore the request.
If a helper receives any other operation, it should silently ignore the request. This leaves room for future operations to be added (older helpers will just ignore the new requests).
Part of the the section called “git(1)” suite
The diff commands git diff-index, git diff-files, and git diff-tree can be told to manipulate differences they find in unconventional ways before showing diff output. The manipulation is collectively called "diffcore transformation". This short note describes what they are and how to use them to produce diff output that is easier to understand than the conventional kind.
The git diff-* family works by first comparing two sets of files:
In all of these cases, the commands themselves first optionally limit the two sets of files by any pathspecs given on their command-lines, and compare corresponding paths in the two resulting sets of files.
The pathspecs are used to limit the world diff operates in. They remove the filepairs outside the specified sets of pathnames. E.g. If the input set of filepairs included:
:100644 100644 bcd1234... 0123456... M junkfile
but the command invocation was git diff-files myfile, then the junkfile entry would be removed from the list because only "myfile" is under consideration.
The result of comparison is passed from these commands to what is internally called "diffcore", in a format similar to what is output when the -p option is not used. E.g.
in-place edit :100644 100644 bcd1234... 0123456... M file0 create :000000 100644 0000000... 1234567... A file4 delete :100644 000000 1234567... 0000000... D file5 unmerged :000000 000000 0000000... 0000000... U file6
The diffcore mechanism is fed a list of such comparison results (each of which is called "filepair", although at this point each of them talks about a single file), and transforms such a list into another list. There are currently 5 such transformations:
These are applied in sequence. The set of filepairs git diff-* commands find are used as the input to diffcore-break, and the output from diffcore-break is used as the input to the next transformation. The final result is then passed to the output routine and generates either diff-raw format (see Output format sections of the manual for git diff-* commands) or diff-patch format.
The second transformation in the chain is diffcore-break, and is controlled by the -B option to the git diff-* commands. This is used to detect a filepair that represents "complete rewrite" and break such filepair into two filepairs that represent delete and create. E.g. If the input contained this filepair:
:100644 100644 bcd1234... 0123456... M file0
and if it detects that the file "file0" is completely rewritten, it changes it to:
:100644 000000 bcd1234... 0000000... D file0 :000000 100644 0000000... 0123456... A file0
For the purpose of breaking a filepair, diffcore-break examines the extent of changes between the contents of the files before and after modification (i.e. the contents that have "bcd1234…" and "0123456…" as their SHA-1 content ID, in the above example). The amount of deletion of original contents and insertion of new material are added together, and if it exceeds the "break score", the filepair is broken into two. The break score defaults to 50% of the size of the smaller of the original and the result (i.e. if the edit shrinks the file, the size of the result is used; if the edit lengthens the file, the size of the original is used), and can be customized by giving a number after "-B" option (e.g. "-B75" to tell it to use 75%).
This transformation is used to detect renames and copies, and is controlled by the -M option (to detect renames) and the -C option (to detect copies as well) to the git diff-* commands. If the input contained these filepairs:
:100644 000000 0123456... 0000000... D fileX :000000 100644 0000000... 0123456... A file0
and the contents of the deleted file fileX is similar enough to the contents of the created file file0, then rename detection merges these filepairs and creates:
:100644 100644 0123456... 0123456... R100 fileX file0
When the "-C" option is used, the original contents of modified files, and deleted files (and also unmodified files, if the "--find-copies-harder" option is used) are considered as candidates of the source files in rename/copy operation. If the input were like these filepairs, that talk about a modified file fileY and a newly created file file0:
:100644 100644 0123456... 1234567... M fileY :000000 100644 0000000... bcd3456... A file0
the original contents of fileY and the resulting contents of file0 are compared, and if they are similar enough, they are changed to:
:100644 100644 0123456... 1234567... M fileY :100644 100644 0123456... bcd3456... C100 fileY file0
In both rename and copy detection, the same "extent of changes" algorithm used in diffcore-break is used to determine if two files are "similar enough", and can be customized to use a similarity score different from the default of 50% by giving a number after the "-M" or "-C" option (e.g. "-M8" to tell it to use 8/10 = 80%).
Note that when rename detection is on but both copy and break detection are off, rename detection adds a preliminary step that first checks if files are moved across directories while keeping their filename the same. If there is a file added to a directory whose contents are sufficiently similar to a file with the same name that got deleted from a different directory, it will mark them as renames and exclude them from the later quadratic step (the one that pairwise compares all unmatched files to find the "best" matches, determined by the highest content similarity). So, for example, if a deleted docs/ext.txt and an added docs/config/ext.txt are similar enough, they will be marked as a rename and prevent an added docs/ext.md that may be even more similar to the deleted docs/ext.txt from being considered as the rename destination in the later step. For this reason, the preliminary "match same filename" step uses a bit higher threshold to mark a file pair as a rename and stop considering other candidates for better matches. At most, one comparison is done per file in this preliminary pass; so if there are several remaining ext.txt files throughout the directory hierarchy after exact rename detection, this preliminary step may be skipped for those files.
Note. When the "-C" option is used with --find-copies-harder option, git diff-* commands feed unmodified filepairs to diffcore mechanism as well as modified ones. This lets the copy detector consider unmodified files as copy source candidates at the expense of making it slower. Without --find-copies-harder, git diff-* commands can detect copies only if the file that was copied happened to have been modified in the same changeset.
This transformation is used to merge filepairs broken by diffcore-break, and not transformed into rename/copy by diffcore-rename, back into a single modification. This always runs when diffcore-break is used.
For the purpose of merging broken filepairs back, it uses a different "extent of changes" computation from the ones used by diffcore-break and diffcore-rename. It counts only the deletion from the original, and does not count insertion. If you removed only 10 lines from a 100-line document, even if you added 910 new lines to make a new 1000-line document, you did not do a complete rewrite. diffcore-break breaks such a case in order to help diffcore-rename to consider such filepairs as a candidate of rename/copy detection, but if filepairs broken that way were not matched with other filepairs to create rename/copy, then this transformation merges them back into the original "modification".
The "extent of changes" parameter can be tweaked from the default 80% (that is, unless more than 80% of the original material is deleted, the broken pairs are merged back into a single modification) by giving a second number to -B option, like these:
Note that earlier implementation left a broken pair as separate creation and deletion patches. This was an unnecessary hack, and the latest implementation always merges all the broken pairs back into modifications, but the resulting patch output is formatted differently for easier review in case of such a complete rewrite by showing the entire contents of the old version prefixed with -, followed by the entire contents of the new version prefixed with +.
This transformation limits the set of filepairs to those that change specified strings between the preimage and the postimage in a certain way. -S<block-of-text> and -G<regular-expression> options are used to specify different ways these strings are sought.
"-S<block-of-text>" detects filepairs whose preimage and postimage have different number of occurrences of the specified block of text. By definition, it will not detect in-file moves. Also, when a changeset moves a file wholesale without affecting the interesting string, diffcore-rename kicks in as usual, and -S omits the filepair (since the number of occurrences of that string didn't change in that rename-detected filepair). When used with --pickaxe-regex, treat the <block-of-text> as an extended POSIX regular expression to match, instead of a literal string.
"-G<regular-expression>" (mnemonic: grep) detects filepairs whose textual diff has an added or a deleted line that matches the given regular expression. This means that it will detect in-file (or what rename-detection considers the same file) moves, which is noise. The implementation runs diff twice and greps, and this can be quite expensive. To speed things up, binary files without textconv filters will be ignored.
When -S or -G are used without --pickaxe-all, only filepairs that match their respective criterion are kept in the output. When --pickaxe-all is used, if even one filepair matches their respective criterion in a changeset, the entire changeset is kept. This behavior is designed to make reviewing changes in the context of the whole changeset easier.
This is used to reorder the filepairs according to the user's (or project's) taste, and is controlled by the -O option to the git diff-* commands.
This takes a text file each of whose lines is a shell glob pattern. Filepairs that match a glob pattern on an earlier line in the file are output before ones that match a later line, and filepairs that do not match any glob pattern are output last.
As an example, a typical orderfile for the core Git probably would look like this:
README Makefile Documentation *.h *.c t
This transformation takes one pathname, and rotates the set of filepairs so that the filepair for the given pathname comes first, optionally discarding the paths that come before it. This is used to implement the --skip-to and the --rotate-to options. It is an error when the specified pathname is not in the set of filepairs, but it is not useful to error out when used with "git log" family of commands, because it is unreasonable to expect that a given path would be modified by each and every commit shown by the "git log" command. For this reason, when used with "git log", the filepair that sorts the same as, or the first one that sorts after, the given pathname is where the output starts.
Use of this transformation combined with diffcore-order will produce unexpected results, as the input to this transformation is likely not sorted when diffcore-order is in effect.
the section called “git-diff(1)”, the section called “git-diff-files(1)”, the section called “git-diff-index(1)”, the section called “git-diff-tree(1)”, the section called “git-format-patch(1)”, the section called “git-log(1)”, the section called “gitglossary(7)”, The Git User's Manual
Part of the the section called “git(1)” suite
A gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected; see the NOTES below for details.
Each line in a gitignore file specifies a pattern. When deciding whether to ignore a path, Git normally checks gitignore patterns from multiple sources, with the following order of precedence, from highest to lowest (within one level of precedence, the last matching pattern decides the outcome):
Which file to place a pattern in depends on how the pattern is meant to be used.
The underlying Git plumbing tools, such as git ls-files and git read-tree, read gitignore patterns specified by command-line options, or from files specified by command-line options. Higher-level Git tools, such as git status and git add, use patterns from the sources specified above.
Two consecutive asterisks ("**") in patterns matched against full pathname may have special meaning:
The optional configuration variable core.excludesFile indicates a path to a file containing patterns of file names to exclude, similar to $GIT_DIR/info/exclude. Patterns in the exclude file are used in addition to those in $GIT_DIR/info/exclude.
The purpose of gitignore files is to ensure that certain files not tracked by Git remain untracked.
To stop tracking a file that is currently tracked, use git rm --cached to remove the file from the index. The filename can then be added to the .gitignore file to stop the file from being reintroduced in later commits.
Git does not follow symbolic links when accessing a .gitignore file in the working tree. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem.
$ git status
[...]
# Untracked files:
[...]
# Documentation/foo.html
# Documentation/gitignore.html
# file.o
# lib.a
# src/internal.o
[...]
$ cat .git/info/exclude
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git status
[...]
# Untracked files:
[...]
# Documentation/foo.html
[...]Another example:
$ cat .gitignore
vmlinux*
$ ls arch/foo/kernel/vm*
arch/foo/kernel/vmlinux.lds.S
$ echo '!/vmlinux*' >arch/foo/kernel/.gitignoreThe second .gitignore prevents Git from ignoring arch/foo/kernel/vmlinux.lds.S.
Example to exclude everything except a specific directory foo/bar (note the /* - without the slash, the wildcard would also exclude everything within foo/bar):
$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/barthe section called “git-rm(1)”, the section called “gitrepository-layout(5)”, the section called “git-check-ignore(1)”
Part of the the section called “git(1)” suite
The examples in this FAQ assume a standard POSIX shell, like bash or dash, and a user, A U Thor, who has the account author on the hosting provider git.example.org.
You should put your personal name, generally a form using a given name and family name. For example, the current maintainer of Git uses "Junio C Hamano". This will be the name portion that is stored in every commit you make.
This configuration doesn't have any effect on authenticating to remote services; for that, see credential.username in the section called “git-config(1)”.
This option changes the size of the buffer that Git uses when pushing data to a remote over HTTP or HTTPS. If the data is larger than this size, libcurl, which handles the HTTP support for Git, will use chunked transfer encoding since it isn't known ahead of time what the size of the pushed data will be.
Leaving this value at the default size is fine unless you know that either the remote server or a proxy in the middle doesn't support HTTP/1.1 (which introduced the chunked transfer encoding) or is known to be broken with chunked data. This is often (erroneously) suggested as a solution for generic push problems, but since almost every server and proxy supports at least HTTP/1.1, raising this value usually doesn't solve most push problems. A server or proxy that didn't correctly support HTTP/1.1 and chunked transfer encoding wouldn't be that useful on the Internet today, since it would break lots of traffic.
Note that increasing this value will increase the memory used on every relevant push that Git does over HTTP or HTTPS, since the entire buffer is allocated regardless of whether or not it is all used. Thus, it's best to leave it at the default unless you are sure you need a different value.
If you haven't specified an editor specifically for Git, it will by default use the editor you've configured using the VISUAL or EDITOR environment variables, or if neither is specified, the system default (which is usually vi). Since some people find vi difficult to use or prefer a different editor, it may be desirable to change the editor used.
If you want to configure a general editor for most programs which need one, you can edit your shell configuration (e.g., ~/.bashrc or ~/.zshenv) to contain a line setting the EDITOR or VISUAL environment variable to an appropriate value. For example, if you prefer the editor nano, then you could write the following:
export VISUAL=nano
If you want to configure an editor specifically for Git, you can either set the core.editor configuration value or the GIT_EDITOR environment variable. You can see the section called “git-var(1)” for details on the order in which these options are consulted.
Note that in all cases, the editor value will be passed to the shell, so any arguments containing spaces should be appropriately quoted. Additionally, if your editor normally detaches from the terminal when invoked, you should specify it with an argument that makes it not do that, or else Git will not see any changes. An example of a configuration addressing both of these issues on Windows would be the configuration "C:\Program Files\Vim\gvim.exe" --nofork, which quotes the filename with spaces and specifies the --nofork option to avoid backgrounding the process.
Git intentionally does not (and will not) provide a configuration variable, such as commit.signoff, to automatically add --signoff by default. The reason is to protect the legal and intentional significance of a sign-off. If there were more automated and widely publicized ways for sign-offs to be appended, it would become easier for someone to argue later that a "Signed-off-by" trailer was just added out of habit or by automation, without the committer's full awareness or intent to certify their agreement with the Developer Certificate of Origin (DCO) or a similar statement. This could undermine the sign-off’s credibility in legal or contractual situations.
There exists format.signoff, but that is a historical mistake, and it is not an excuse to add more mistakes of the same kind on top.
The easiest way to do this is to use a credential helper via the credential.helper configuration. Most systems provide a standard choice to integrate with the system credential manager. For example, Git for Windows provides the wincred credential manager, macOS has the osxkeychain credential manager, and Unix systems with a standard desktop environment can use the libsecret credential manager. All of these store credentials in an encrypted store to keep your passwords or tokens secure.
In addition, you can use the store credential manager which stores in a file in your home directory, or the cache credential manager, which does not permanently store your credentials, but does prevent you from being prompted for them for a certain period of time.
You can also just enter your password when prompted. While it is possible to place the password (which must be percent-encoded) in the URL, this is not particularly secure and can lead to accidental exposure of credentials, so it is not recommended.
The credential.helper configuration option can also take an arbitrary shell command that produces the credential protocol on standard output. This is useful when passing credentials into a container, for example.
Such a shell command can be specified by starting the option value with an exclamation point. If your password or token were stored in the GIT_TOKEN, you could run the following command to set your credential helper:
$ git config credential.helper \
'!f() { echo username=author; echo "password=$GIT_TOKEN"; };f'Usually, if the password or token is invalid, Git will erase it and prompt for a new one. However, there are times when this doesn't always happen. To change the password or token, you can erase the existing credentials and then Git will prompt for new ones. To erase credentials, use a syntax like the following (substituting your username and the hostname):
$ echo url=https://author@git.example.org | git credential reject
With most hosting providers that support SSH, a single key pair uniquely identifies a user. Therefore, to use multiple accounts, it's necessary to create a key pair for each account. If you're using a reasonably modern OpenSSH version, you can create a new key pair with something like ssh-keygen -t ed25519 -f ~/.ssh/id_committer. You can then register the public key (in this case, ~/.ssh/id_committer.pub; note the .pub) with the hosting provider.
Most hosting providers use a single SSH account for pushing; that is, all users push to the git account (e.g., git@git.example.org). If that's the case for your provider, you can set up multiple aliases in SSH to make it clear which key pair to use. For example, you could write something like the following in ~/.ssh/config, substituting the proper private key file:
# This is the account for author on git.example.org.
Host example_author
HostName git.example.org
User git
# This is the key pair registered for author with git.example.org.
IdentityFile ~/.ssh/id_author
IdentitiesOnly yes
# This is the account for committer on git.example.org.
Host example_committer
HostName git.example.org
User git
# This is the key pair registered for committer with git.example.org.
IdentityFile ~/.ssh/id_committer
IdentitiesOnly yesThen, you can adjust your push URL to use git@example_author or git@example_committer instead of git@example.org (e.g., git remote set-url git@example_author:org1/project1.git).
First, decide whether you want to do this at all. Git works best when you push or pull your work using the typical git push and git fetch commands and isn't designed to share a working tree across systems. This is potentially risky and in some cases can cause repository corruption or data loss.
Usually, doing so will cause git status to need to re-read every file in the working tree. Additionally, Git's security model does not permit sharing a working tree across untrusted users, so it is only safe to sync a working tree if it will only be used by a single user across all machines.
It is important not to use a cloud syncing service to sync any portion of a Git repository, since this can cause corruption, such as missing objects, changed or added files, broken refs, and a wide variety of other problems. These services tend to sync file by file on a continuous basis and don't understand the structure of a Git repository. This is especially bad if they sync the repository in the middle of it being updated, since that is very likely to cause incomplete or partial updates and therefore data loss.
An example of the kind of corruption that can occur is conflicts over the state of refs, such that both sides end up with different commits on a branch that the other doesn't have. This can result in important objects becoming unreferenced and possibly pruned by git gc, causing data loss.
Therefore, it's better to push your work to either the other system or a central server using the normal push and pull mechanism. In Git 2.51, Git learned to import and export stashes, so it's possible to synchronize the state of the working tree by stashing it with git stash, then exporting either all stashes with git stash export --to-ref refs/heads/stashes (assuming you want to export to the stashes branch) or selecting stashes by adding their numbers to the end of that command. It's also possible to include untracked files by using the --include-untracked argument when stashing the data in the first place, but be careful not to do this if any of these contain sensitive information.
You can then push the stashes branch (or whatever branch you've exported to), fetch them to the local system (such as with git fetch origin +stashes:stashes), and import the stashes on the other system with git stash import stashes (again, changing the name as necessary). Applying the changes to the working tree can be done with git stash pop or git stash apply. This is the approach that is most robust and most likely to avoid unintended problems.
Having said that, there are some cases where people nevertheless prefer to share a working tree across systems. If you do this, the recommended approach is to use rsync -a --delete-after (ideally with an encrypted connection such as with ssh) on the root of repository. You should ensure several things when you do this:
The repository (including all worktrees and the Git directory) is in a quiescent state for the duration of the transfer (that is, no operations of any sort are taking place on it, including background operations like git gc and operations invoked by your editor).
Be aware that even with these recommendations, syncing working trees in this way has some risk since it bypasses Git's normal integrity checking for repositories, so having backups is advised. You may also wish to do a git fsck to verify the integrity of your data on the destination system after syncing.
Git doesn't provide a way to do this. The reason is that if Git needs to overwrite this file, such as during a checkout, it doesn't know whether the changes to the file are precious and should be kept, or whether they are irrelevant and can safely be destroyed. Therefore, it has to take the safe route and always preserve them.
It's tempting to try to use certain features of git update-index, namely the assume-unchanged and skip-worktree bits, but these don't work properly for this purpose and shouldn't be used this way.
If your goal is to modify a configuration file, it can often be helpful to have a file checked into the repository which is a template or set of defaults which can then be copied alongside and modified as appropriate. This second, modified file is usually ignored to prevent accidentally committing it.
Yes, Git supports the use of proxies. Git honors the standard http_proxy, https_proxy, and no_proxy environment variables commonly used on Unix, and it also can be configured with http.proxy and similar options for HTTPS (see the section called “git-config(1)”). The http.proxy and related options can be customized on a per-URL pattern basis. In addition, Git can in theory function normally with transparent proxies that exist on the network.
For SSH, Git can support a proxy using OpenSSH's ProxyCommand. Commonly used tools include netcat and socat. However, they must be configured not to exit when seeing EOF on standard input, which usually means that netcat will require -q and socat will require a timeout with something like -t 10. This is required because the way the Git SSH server knows that no more requests will be made is an EOF on standard input, but when that happens, the server may not have yet processed the final request, so dropping the connection at that point would interrupt that request.
An example configuration entry in ~/.ssh/config with an HTTP proxy might look like this:
Host git.example.org
User git
ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080Note that in all cases, for Git to work properly, the proxy must be completely transparent. The proxy cannot modify, tamper with, or buffer the connection in any way, or Git will almost certainly fail to work. Note that many proxies, including many TLS middleboxes, Windows antivirus and firewall programs other than Windows Defender and Windows Firewall, and filtering proxies fail to meet this standard, and as a result end up breaking Git. Because of the many reports of problems and their poor security history, we recommend against the use of these classes of software and devices.
In general, there are a variety of problems that can occur when using squash merges to merge two branches multiple times. These can include seeing extra commits in git log output, with a GUI, or when using the ... notation to express a range, as well as the possibility of needing to re-resolve conflicts again and again.
When Git does a normal merge between two branches, it considers exactly three points: the two branches and a third commit, called the merge base, which is usually the common ancestor of the commits. The result of the merge is the sum of the changes between the merge base and each head. When you merge two branches with a regular merge commit, this results in a new commit which will end up as a merge base when they're merged again, because there is now a new common ancestor. Git doesn't have to consider changes that occurred before the merge base, so you don't have to re-resolve any conflicts you resolved before.
When you perform a squash merge, a merge commit isn't created; instead, the changes from one side are applied as a regular commit to the other side. This means that the merge base for these branches won't have changed, and so when Git goes to perform its next merge, it considers all of the changes that it considered the last time plus the new changes. That means any conflicts may need to be re-resolved. Similarly, anything using the ... notation in git diff, git log, or a GUI will result in showing all of the changes since the original merge base.
As a consequence, if you want to merge two long-lived branches repeatedly, it's best to always use a regular merge commit.
By default, when Git does a merge, it uses a strategy called the ort strategy, which does a fancy three-way merge. In such a case, when Git performs the merge, it considers exactly three points: the two heads and a third point, called the merge base, which is usually the common ancestor of those commits. Git does not consider the history or the individual commits that have happened on those branches at all.
As a result, if both sides have a change and one side has reverted that change, the result is to include the change. This is because the code has changed on one side and there is no net change on the other, and in this scenario, Git adopts the change.
If this is a problem for you, you can do a rebase instead, rebasing the branch with the revert onto the other branch. A rebase in this scenario will revert the change, because a rebase applies each individual commit, including the revert. Note that rebases rewrite history, so you should avoid rebasing published branches unless you're sure you're comfortable with that. See the NOTES section in the section called “git-rebase(1)” for more details.
The only safe place to make these changes is on the remote repository (i.e., the Git server), usually in the pre-receive hook or in a continuous integration (CI) system. These are the locations in which policy can be enforced effectively.
It's common to try to use pre-commit hooks (or, for commit messages, commit-msg hooks) to check these things, which is great if you're working as a solo developer and want the tooling to help you. However, using hooks on a developer machine is not effective as a policy control because a user can bypass these hooks with --no-verify without being noticed (among various other ways). Git assumes that the user is in control of their local repositories and doesn't try to prevent this or tattle on the user.
In addition, some advanced users find pre-commit hooks to be an impediment to workflows that use temporary commits to stage work in progress or that create fixup commits, so it's better to push these kinds of checks to the server anyway.
Git works best when you store text files as UTF-8. Many programs on Windows support UTF-8, but some do not and only use the little-endian UTF-16 format, which Git detects as binary. If you can't use UTF-8 with your programs, you can specify a working tree encoding that indicates which encoding your files should be checked out with, while still storing these files as UTF-8 in the repository. This allows tools like the section called “git-diff(1)” to work as expected, while still allowing your tools to work.
To do so, you can specify a the section called “gitattributes(5)” pattern with the working-tree-encoding attribute. For example, the following pattern sets all C files to use UTF-16LE-BOM, which is a common encoding on Windows:
*.c working-tree-encoding=UTF-16LE-BOM
You will need to run git add --renormalize to have this take effect. Note that if you are making these changes on a project that is used across platforms, you'll probably want to make it in a per-user configuration file or in the one in $GIT_DIR/info/attributes, since making it in a .gitattributes file in the repository will apply to all users of the repository.
See the following entry for information about normalizing line endings as well, and see the section called “gitattributes(5)” for more information about attribute files.
By default, Git expects files to be stored with Unix line endings. As such, the carriage return (^M) that is part of a Windows line ending is shown because it is considered to be trailing whitespace. Git defaults to showing trailing whitespace only on new lines, not existing ones.
You can store the files in the repository with Unix line endings and convert them automatically to your platform's line endings. To do that, set the configuration option core.eol to native and see the question on recommended storage settings for information about how to configure files as text or binary.
You can also control this behavior with the core.whitespace setting if you don't wish to remove the carriage returns from your line endings.
Internally, Git always stores file names as sequences of bytes and doesn't perform any encoding or case folding. However, Windows and macOS by default both perform case folding on file names. As a result, it's possible to end up with multiple files or directories whose names differ only in case. Git can handle this just fine, but the file system can store only one of these files, so when Git reads the other file to see its contents, it looks modified.
It's best to remove one of the files such that you only have one file. You can do this with commands like the following (assuming two files AFile.txt and afile.txt) on an otherwise clean working tree:
$ git rm --cached AFile.txt $ git commit -m 'Remove files conflicting in case' $ git checkout .
This avoids touching the disk, but removes the additional file. Your project may prefer to adopt a naming convention, such as all-lowercase names, to avoid this problem from occurring again; such a convention can be checked using a pre-receive hook or as part of a continuous integration (CI) system.
It is also possible for perpetually modified files to occur on any platform if a smudge or clean filter is in use on your system but a file was previously committed without running the smudge or clean filter. To fix this, run the following on an otherwise clean working tree:
$ git add --renormalize .
While Git can store and handle any file of any type, there are some settings that work better than others. In general, we recommend that text files be stored in UTF-8 without a byte-order mark (BOM) with LF (Unix-style) endings. We also recommend the use of UTF-8 (again, without BOM) in commit messages. These are the settings that work best across platforms and with tools such as git diff and git merge.
Additionally, if you have a choice between storage formats that are text based or non-text based, we recommend storing files in the text format and, if necessary, transforming them into the other format. For example, a text-based SQL dump with one record per line will work much better for diffing and merging than an actual database file. Similarly, text-based formats such as Markdown and AsciiDoc will work better than binary formats such as Microsoft Word and PDF.
Similarly, storing binary dependencies (e.g., shared libraries or JAR files) or build products in the repository is generally not recommended. Dependencies and build products are best stored on an artifact or package server with only references, URLs, and hashes stored in the repository.
We also recommend setting a the section called “gitattributes(5)” file to explicitly mark which files are text and which are binary. If you want Git to guess, you can set the attribute text=auto.
With text files, Git will generally ensure that LF endings are used in the repository. The core.autocrlf and core.eol configuration variables specify what line-ending convention is followed when any text file is checked out. You can also use the eol attribute (e.g., eol=crlf) to override which files get what line-ending treatment.
For example, generally shell files must have LF endings and batch files must have CRLF endings, so the following might be appropriate in some projects:
# By default, guess. * text=auto # Mark all C files as text. *.c text # Ensure all shell files have LF endings and all batch files have CRLF # endings in the working tree and both have LF in the repo. *.sh text eol=lf *.bat text eol=crlf # Mark all JPEG files as binary. *.jpg binary
These settings help tools pick the right format for output such as patches and result in files being checked out in the appropriate line ending for the platform.
Part of the the section called “git(1)” suite
Hooks are programs you can place in a hooks directory to trigger actions at certain points in git's execution. Hooks that don't have the executable bit set are ignored.
By default the hooks directory is $GIT_DIR/hooks, but that can be changed via the core.hooksPath configuration variable (see the section called “git-config(1)”).
Before Git invokes a hook, it changes its working directory to either $GIT_DIR in a bare repository or the root of the working tree in a non-bare repository. An exception are hooks triggered during a push (pre-receive, update, post-receive, post-update, push-to-checkout) which are always executed in $GIT_DIR.
Environment variables, such as GIT_DIR, GIT_WORK_TREE, etc., are exported so that Git commands run by the hook can correctly locate the repository. If your hook needs to invoke Git commands in a foreign repository or in a different working tree of the same repository, then it should clear these environment variables so they do not interfere with Git operations at the foreign location. For example:
local_desc=$(git describe) foreign_desc=$(unset $(git rev-parse --local-env-vars); git -C ../foreign-repo describe)
Hooks can get their arguments via the environment, command-line arguments, and stdin. See the documentation for each hook below for details.
git init may copy hooks to the new repository, depending on its configuration. See the "TEMPLATE DIRECTORY" section in the section called “git-init(1)” for details. When the rest of this document refers to "default hooks" it's talking about the default template shipped with Git.
The currently supported hooks are described below.
This hook is invoked by the section called “git-am(1)”. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with a non-zero status causes git am to abort before applying the patch.
The hook is allowed to edit the message file in place, and can be used to normalize the message into some project standard format. It can also be used to refuse the commit after inspecting the message file.
The default applypatch-msg hook, when enabled, runs the commit-msg hook, if the latter is enabled.
This hook is invoked by the section called “git-am(1)”. It takes no parameter, and is invoked after the patch is applied, but before a commit is made.
If it exits with non-zero status, then the working tree will not be committed after applying the patch.
It can be used to inspect the current working tree and refuse to make a commit if it does not pass certain tests.
The default pre-applypatch hook, when enabled, runs the pre-commit hook, if the latter is enabled.
This hook is invoked by the section called “git-am(1)”. It takes no parameter, and is invoked after the patch is applied and a commit is made.
This hook is meant primarily for notification, and cannot affect the outcome of git am.
This hook is invoked by the section called “git-commit(1)”, and can be bypassed with the --no-verify option. It takes no parameters, and is invoked before obtaining the proposed commit log message and making a commit. Exiting with a non-zero status from this script causes the git commit command to abort before creating a commit.
All the git commit hooks are invoked with the environment variable GIT_EDITOR=: if the command will not bring up an editor to modify the commit message.
The default pre-commit hook, when enabled, prevents the introduction of non-ASCII filenames and lines with trailing whitespace. The non-ASCII check can be turned off by setting the hooks.allownonascii config option to true.
This hook is invoked by the section called “git-merge(1)”, and can be bypassed with the --no-verify option. It takes no parameters, and is invoked after the merge has been carried out successfully and before obtaining the proposed commit log message to make a commit. Exiting with a non-zero status from this script causes the git merge command to abort before creating a commit.
The default pre-merge-commit hook, when enabled, runs the pre-commit hook, if the latter is enabled.
This hook is invoked with the environment variable GIT_EDITOR=: if the command will not bring up an editor to modify the commit message.
If the merge cannot be carried out automatically, the conflicts need to be resolved and the result committed separately (see the section called “git-merge(1)”). At that point, this hook will not be executed, but the pre-commit hook will, if it is enabled.
This hook is invoked by the section called “git-commit(1)” right after preparing the default log message, and before the editor is started.
It takes one to three parameters. The first is the name of the file that contains the commit log message. The second is the source of the commit message, and can be: message (if a -m or -F option was given); template (if a -t option was given or the configuration option commit.template is set); merge (if the commit is a merge or a .git/MERGE_MSG file exists); squash (if a .git/SQUASH_MSG file exists); or commit, followed by a commit object name (if a -c, -C or --amend option was given).
If the exit status is non-zero, git commit will abort.
The purpose of the hook is to edit the message file in place, and it is not suppressed by the --no-verify option. A non-zero exit means a failure of the hook and aborts the commit. It should not be used as a replacement for the pre-commit hook.
The sample prepare-commit-msg hook that comes with Git removes the help message found in the commented portion of the commit template.
This hook is invoked by the section called “git-commit(1)” and the section called “git-merge(1)”, and can be bypassed with the --no-verify option. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with a non-zero status causes the command to abort.
The hook is allowed to edit the message file in place, and can be used to normalize the message into some project standard format. It can also be used to refuse the commit after inspecting the message file.
The default commit-msg hook, when enabled, detects duplicate Signed-off-by trailers, and aborts the commit if one is found.
This hook is invoked by the section called “git-commit(1)”. It takes no parameters, and is invoked after a commit is made.
This hook is meant primarily for notification, and cannot affect the outcome of git commit.
This hook is called by the section called “git-rebase(1)” and can be used to prevent a branch from getting rebased. The hook may be called with one or two parameters. The first parameter is the upstream from which the series was forked. The second parameter is the branch being rebased, and is not set when rebasing the current branch.
This hook is invoked when a the section called “git-checkout(1)” or the section called “git-switch(1)” is run after having updated the worktree. The hook is given three parameters: the ref of the previous HEAD, the ref of the new HEAD (which may or may not have changed), and a flag indicating whether the checkout was a branch checkout (changing branches, flag=1) or a file checkout (retrieving a file from the index, flag=0). This hook cannot affect the outcome of git switch or git checkout, other than that the hook's exit status becomes the exit status of these two commands.
It is also run after the section called “git-clone(1)”, unless the --no-checkout (-n) option is used. The first parameter given to the hook is the null-ref, the second the ref of the new HEAD and the flag is always 1. Likewise for git worktree add unless --no-checkout is used.
This hook can be used to perform repository validity checks, auto-display differences from the previous HEAD if different, or set working dir metadata properties.
This hook is invoked by the section called “git-merge(1)”, which happens when a git pull is done on a local repository. The hook takes a single parameter, a status flag specifying whether or not the merge being done was a squash merge. This hook cannot affect the outcome of git merge and is not executed, if the merge failed due to conflicts.
This hook can be used in conjunction with a corresponding pre-commit hook to save and restore any form of metadata associated with the working tree (e.g.: permissions/ownership, ACLS, etc). See contrib/hooks/setgitperms.perl for an example of how to do this.
This hook is called by the section called “git-push(1)” and can be used to prevent a push from taking place. The hook is called with two parameters which provide the name and location of the destination remote, if a named remote is not being used both values will be the same.
Information about what is to be pushed is provided on the hook's standard input with lines of the form:
<local-ref> SP <local-object-name> SP <remote-ref> SP <remote-object-name> LF
For instance, if the command git push origin master:foreign were run the
hook would receive a line like the following:
refs/heads/master 67890 refs/heads/foreign 12345
although the full object name would be supplied. If the foreign ref does not yet exist the <remote-object-name> will be the all-zeroes object name. If a ref is to be deleted, the <local-ref> will be supplied as (delete) and the <local-object-name> will be the all-zeroes object name. If the local commit was specified by something other than a name which could be expanded (such as HEAD~, or an object name) it will be supplied as it was originally given.
If this hook exits with a non-zero status, git push will abort without pushing anything. Information about why the push is rejected may be sent to the user by writing to standard error.
This hook is invoked by the section called “git-receive-pack(1)” when it reacts to git push and updates reference(s) in its repository. Just before starting to update refs on the remote repository, the pre-receive hook is invoked. Its exit status determines the success or failure of the update.
This hook executes once for the receive operation. It takes no arguments, but for each ref to be updated it receives on standard input a line of the format:
<old-oid> SP <new-oid> SP <ref-name> LF
where <old-oid> is the old object name stored in the ref, <new-oid> is the new object name to be stored in the ref and <ref-name> is the full name of the ref. When creating a new ref, <old-oid> is the all-zeroes object name.
If the hook exits with non-zero status, none of the refs will be updated. If the hook exits with zero, updating of individual refs can still be prevented by the update hook.
Both standard output and standard error output are forwarded to git send-pack on the other end, so you can simply echo messages for the user.
The number of push options given on the command line of git push --push-option=... can be read from the environment variable GIT_PUSH_OPTION_COUNT, and the options themselves are found in GIT_PUSH_OPTION_0, GIT_PUSH_OPTION_1,… If it is negotiated to not use the push options phase, the environment variables will not be set. If the client selects to use push options, but doesn't transmit any, the count variable will be set to zero, GIT_PUSH_OPTION_COUNT=0.
See the section on "Quarantine Environment" in the section called “git-receive-pack(1)” for some caveats.
This hook is invoked by the section called “git-receive-pack(1)” when it reacts to git push and updates reference(s) in its repository. Just before updating the ref on the remote repository, the update hook is invoked. Its exit status determines the success or failure of the ref update.
The hook executes once for each ref to be updated, and takes three parameters:
A zero exit from the update hook allows the ref to be updated. Exiting with a non-zero status prevents git receive-pack from updating that ref.
This hook can be used to prevent forced update on certain refs by making sure that the object name is a commit object that is a descendant of the commit object named by the old object name. That is, to enforce a "fast-forward only" policy.
It could also be used to log the old..new status. However, it does not know the entire set of branches, so it would end up firing one e-mail per ref when used naively, though. The post-receive hook is more suited to that.
In an environment that restricts the users' access only to git commands over the wire, this hook can be used to implement access control without relying on filesystem ownership and group membership. See the section called “git-shell(1)” for how you might use the login shell to restrict the user's access to only git commands.
Both standard output and standard error output are forwarded to git send-pack on the other end, so you can simply echo messages for the user.
The default update hook, when enabled--and with hooks.allowunannotated config option unset or set to false--prevents unannotated tags from being pushed.
This hook is invoked by the section called “git-receive-pack(1)”. If the server has set the multi-valued config variable receive.procReceiveRefs, and the commands sent to receive-pack have matching reference names, these commands will be executed by this hook, instead of by the internal execute_commands() function. This hook is responsible for updating the relevant references and reporting the results back to receive-pack.
This hook executes once for the receive operation. It takes no arguments, but uses a pkt-line format protocol to communicate with receive-pack to read commands, push-options and send results. In the following example for the protocol, the letter S stands for receive-pack and the letter H stands for this hook.
# Version and features negotiation. S: PKT-LINE(version=1\0push-options atomic...) S: flush-pkt H: PKT-LINE(version=1\0push-options...) H: flush-pkt
# Send commands from server to the hook. S: PKT-LINE(<old-oid> <new-oid> <ref>) S: ... ... S: flush-pkt # Send push-options only if the 'push-options' feature is enabled. S: PKT-LINE(push-option) S: ... ... S: flush-pkt
# Receive results from the hook. # OK, run this command successfully. H: PKT-LINE(ok <ref>) # NO, I reject it. H: PKT-LINE(ng <ref> <reason>) # Fall through, let 'receive-pack' execute it. H: PKT-LINE(ok <ref>) H: PKT-LINE(option fall-through) # OK, but has an alternate reference. The alternate reference name # and other status can be given in option directives. H: PKT-LINE(ok <ref>) H: PKT-LINE(option refname <refname>) H: PKT-LINE(option old-oid <old-oid>) H: PKT-LINE(option new-oid <new-oid>) H: PKT-LINE(option forced-update) H: ... ... H: flush-pkt
Each command for the proc-receive hook may point to a pseudo-reference and always has a zero-old as its old-oid, while the proc-receive hook may update an alternate reference and the alternate reference may exist already with a non-zero old-oid. For this case, this hook will use "option" directives to report extended attributes for the reference given by the leading "ok" directive.
The report of the commands of this hook should have the same order as the input. The exit status of the proc-receive hook only determines the success or failure of the group of commands sent to it, unless atomic push is in use.
This hook is invoked by the section called “git-receive-pack(1)” when it reacts to git push and updates reference(s) in its repository. The hook executes on the remote repository once after all the proposed ref updates are processed and if at least one ref is updated as the result.
The hook takes no arguments. It receives one line on standard input for each ref that is successfully updated following the same format as the pre-receive hook.
This hook does not affect the outcome of git receive-pack, as it is called after the real work is done.
This supersedes the post-update hook in that it gets both old and new values of all the refs in addition to their names.
Both standard output and standard error output are forwarded to git send-pack on the other end, so you can simply echo messages for the user.
The default post-receive hook is empty, but there is a sample script post-receive-email provided in the contrib/hooks directory in Git distribution, which implements sending commit emails.
The number of push options given on the command line of git push --push-option=... can be read from the environment variable GIT_PUSH_OPTION_COUNT, and the options themselves are found in GIT_PUSH_OPTION_0, GIT_PUSH_OPTION_1,… If it is negotiated to not use the push options phase, the environment variables will not be set. If the client selects to use push options, but doesn't transmit any, the count variable will be set to zero, GIT_PUSH_OPTION_COUNT=0.
See the "post-receive" section in the section called “git-receive-pack(1)” for additional details.
This hook is invoked by the section called “git-receive-pack(1)” when it reacts to git push and updates reference(s) in its repository. It executes on the remote repository once after all the refs have been updated.
It takes a variable number of parameters, each of which is the name of ref that was actually updated.
This hook is meant primarily for notification, and cannot affect the outcome of git receive-pack.
The post-update hook can tell what are the heads that were pushed, but it does not know what their original and updated values are, so it is a poor place to do log old..new. The post-receive hook does get both original and updated values of the refs. You might consider it instead if you need them.
When enabled, the default post-update hook runs git update-server-info to keep the information used by dumb transports (e.g., HTTP) up to date. If you are publishing a Git repository that is accessible via HTTP, you should probably enable this hook.
Both standard output and standard error output are forwarded to git send-pack on the other end, so you can simply echo messages for the user.
This hook is invoked by any Git command that performs reference updates. It executes whenever a reference transaction is prepared, committed or aborted and may thus get called multiple times. The hook also supports symbolic reference updates.
The hook takes exactly one argument, which is the current state the given reference transaction is in:
For each reference update that was added to the transaction, the hook receives on standard input a line of the format:
<old-value> SP <new-value> SP <ref-name> LF
where <old-value> is the old object name passed into the reference transaction, <new-value> is the new object name to be stored in the ref and <ref-name> is the full name of the ref. When force updating the reference regardless of its current value or when the reference is to be created anew, <old-value> is the all-zeroes object name. To distinguish these cases, you can inspect the current value of <ref-name> via git rev-parse.
For symbolic reference updates the <old_value> and <new-value> fields could denote references instead of objects. A reference will be denoted with a ref: prefix, like ref:<ref-target>.
The exit status of the hook is ignored for any state except for the "prepared" state. In the "prepared" state, a non-zero exit status will cause the transaction to be aborted. The hook will not be called with "aborted" state in that case.
This hook is invoked by the section called “git-receive-pack(1)” when it reacts to git push and updates reference(s) in its repository, and when the push tries to update the branch that is currently checked out and the receive.denyCurrentBranch configuration variable is set to updateInstead. Such a push by default is refused if the working tree and the index of the remote repository has any difference from the currently checked out commit; when both the working tree and the index match the current commit, they are updated to match the newly pushed tip of the branch. This hook is to be used to override the default behaviour.
The hook receives the commit with which the tip of the current branch is going to be updated. It can exit with a non-zero status to refuse the push (when it does so, it must not modify the index or the working tree). Or it can make any necessary changes to the working tree and to the index to bring them to the desired state when the tip of the current branch is updated to the new commit, and exit with a zero status.
For example, the hook can simply run git read-tree -u -m HEAD "$1" in order to emulate git fetch that is run in the reverse direction with git push, as the two-tree form of git read-tree -u -m is essentially the same as git switch or git checkout that switches branches while keeping the local changes in the working tree that do not interfere with the difference between the branches.
This hook is invoked by git gc --auto (see the section called “git-gc(1)”). It takes no parameter, and exiting with non-zero status from this script causes the git gc --auto to abort.
This hook is invoked by commands that rewrite commits (the section called “git-commit(1)” when called with --amend and the section called “git-rebase(1)”; however, full-history (re)writing tools like the section called “git-fast-import(1)” or git-filter-repo typically do not call it!). Its first argument denotes the command it was invoked by: currently one of amend or rebase. Further command-dependent arguments may be passed in the future.
The hook receives a list of the rewritten commits on stdin, in the format
<old-object-name> SP <new-object-name> [ SP <extra-info> ] LF
The extra-info is again command-dependent. If it is empty, the preceding SP is also omitted. Currently, no commands pass any extra-info.
The hook always runs after the automatic note copying (see "notes.rewrite.<command>" in the section called “git-config(1)”) has happened, and thus has access to these notes.
The following command-specific comments apply:
For the squash and fixup operation, all commits that were squashed are listed as being rewritten to the squashed commit. This means that there will be several lines sharing the same new-object-name.
The commits are guaranteed to be listed in the order that they were processed by rebase.
This hook is invoked by the section called “git-send-email(1)”.
It takes these command line arguments. They are, 1. the name of the file which holds the contents of the email to be sent. 2. The name of the file which holds the SMTP headers of the email.
The SMTP headers are passed in the exact same way as they are passed to the user's Mail Transport Agent (MTA). In effect, the email given to the user's MTA, is the contents of $2 followed by the contents of $1.
An example of a few common headers is shown below. Take notice of the capitalization and multi-line tab structure.
From: Example <from@example.com>
To: to@example.com
Cc: cc@example.com,
A <author@example.com>,
One <one@example.com>,
two@example.com
Subject: PATCH-STRINGExiting with a non-zero status causes git send-email to abort before sending any e-mails.
The following environment variables are set when executing the hook.
These variables may for instance be used to validate patch series.
The sample sendemail-validate hook that comes with Git checks that all sent patches (excluding the cover letter) can be applied on top of the upstream repository default branch without conflicts. Some placeholders are left for additional validation steps to be performed after all patches of a given series have been applied.
This hook is invoked when the configuration option core.fsmonitor is set to .git/hooks/fsmonitor-watchman or .git/hooks/fsmonitor-watchmanv2 depending on the version of the hook to use.
Version 1 takes two arguments, a version (1) and the time in elapsed nanoseconds since midnight, January 1, 1970.
Version 2 takes two arguments, a version (2) and a token that is used for identifying changes since the token. For watchman this would be a clock id. This version must output to stdout the new token followed by a NUL before the list of files.
The hook should output to stdout the list of all files in the working directory that may have changed since the requested time. The logic should be inclusive so that it does not miss any potential changes. The paths should be relative to the root of the working directory and be separated by a single NUL.
It is OK to include files which have not actually changed. All changes including newly-created and deleted files should be included. When files are renamed, both the old and the new name should be included.
Git will limit what files it checks for changes as well as which directories are checked for untracked files based on the path names given.
An optimized way to tell git "all files have changed" is to return the filename /.
The exit status determines whether git will use the data from the hook to limit its search. On error, it will fall back to verifying all files and folders.
This hook is invoked by git-p4 submit.
The p4-changelist hook is executed after the changelist message has been edited by the user. It can be bypassed with the --no-verify option. It takes a single parameter, the name of the file that holds the proposed changelist text. Exiting with a non-zero status causes the command to abort.
The hook is allowed to edit the changelist file and can be used to normalize the text into some project standard format. It can also be used to refuse the Submit after inspect the message file.
Run git-p4 submit --help for details.
This hook is invoked by git-p4 submit.
The p4-prepare-changelist hook is executed right after preparing the default changelist message and before the editor is started. It takes one parameter, the name of the file that contains the changelist text. Exiting with a non-zero status from the script will abort the process.
The purpose of the hook is to edit the message file in place, and it is not suppressed by the --no-verify option. This hook is called even if --prepare-p4-only is set.
Run git-p4 submit --help for details.
This hook is invoked by git-p4 submit.
The p4-post-changelist hook is invoked after the submit has successfully occurred in P4. It takes no parameters and is meant primarily for notification and cannot affect the outcome of the git p4 submit action.
Run git-p4 submit --help for details.
This hook is invoked by git-p4 submit. It takes no parameters and nothing from standard input. Exiting with non-zero status from this script prevent git-p4 submit from launching. It can be bypassed with the --no-verify command line option. Run git-p4 submit --help for details.
This hook is invoked when the index is written in read-cache.c do_write_locked_index.
The first parameter passed to the hook is the indicator for the working directory being updated. "1" meaning working directory was updated or "0" when the working directory was not updated.
The second parameter passed to the hook is the indicator for whether or not the index was updated and the skip-worktree bit could have changed. "1" meaning skip-worktree bits could have been updated and "0" meaning they were not.
Only one parameter should be set to "1" when the hook runs. The hook running passing "1", "1" should not be possible.
Part of the the section called “git(1)” suite
Displays changes in a repository or a selected set of commits. This includes visualizing the commit graph, showing information related to each commit, and the files in the trees of each revision.
To control which revisions to show, gitk supports most options applicable to the git rev-list command. It also supports a few options applicable to the git diff-* commands to control how the changes each commit introduces are shown. Finally, it supports some gitk-specific options.
gitk generally only understands options with arguments in the stuck form (see the section called “gitcli(7)”) due to limitations in the command-line parser.
This manual page describes only the most frequently used options. See the section called “git-rev-list(1)” for a complete list.
Trace the evolution of the line range given by <start>,<end>, or by the function name regex <funcname>, within the <file>. You may not give any pathspec limiters. This is currently limited to a walk starting from a single revision, i.e., you may only give zero or one positive revision arguments, and <start> and <end> (or <funcname>) must exist in the starting revision. You can specify this option more than once. Implies --patch. Patch output can be suppressed using --no-patch, but other diff formats (namely --raw, --numstat, --shortstat, --dirstat, --summary, --name-only, --name-status, --check) are not currently implemented.
<start> and <end> can take one of these forms:
<number>
If <start> or <end> is a number, it specifies an absolute line number (lines count from 1).
/<regex>/
This form will use the first line matching the given POSIX <regex>. If <start> is a regex, it will search from the end of the previous -L range, if any, otherwise from the start of file. If <start> is ^/<regex>/, it will search from the start of file. If <end> is a regex, it will search starting at the line given by <start>.
+<offset> or -<offset>
This is only valid for <end> and will specify a number of lines before or after the line given by <start>.
If :<funcname> is given in place of <start> and <end>, it is a regular expression that denotes the range from the first funcname line that matches <funcname>, up to the next funcname line. :<funcname> searches from the end of the previous -L range, if any, otherwise from the start of file. ^:<funcname> searches from the start of file. The function names are determined in the same way as git diff works out patch hunk headers (see Defining a custom hunk-header in the section called “gitattributes(5)”).
User configuration and preferences are stored at:
If neither of the above exist then $XDG_CONFIG_HOME/git/gitk is created and used by default. If $XDG_CONFIG_HOME is not set it defaults to $HOME/.config in all cases.
Gitk was the first graphical repository browser, written by Paul Mackerras in Tcl/Tk.
gitk is actually maintained as an independent project, but stable versions are distributed as part of the Git suite for the convenience of end users.
gitk-git/ comes from Johannes Sixt's gitk project:
https://github.com/j6t/gitk
Part of the the section called “git(1)” suite
If the file .mailmap exists at the toplevel of the repository, or at the location pointed to by the mailmap.file or mailmap.blob configuration options (see the section called “git-config(1)”), it is used to map author and committer names and email addresses to canonical real names and email addresses.
The # character begins a comment to the end of line, blank lines are ignored.
In the simple form, each line in the file consists of the canonical real name of an author, whitespace, and an email address used in the commit (enclosed by < and >) to map to the name. For example:
Proper Name <commit@email.xx>
The more complex forms are:
<proper@email.xx> <commit@email.xx>
which allows mailmap to replace only the email part of a commit, and:
Proper Name <proper@email.xx> <commit@email.xx>
which allows mailmap to replace both the name and the email of a commit matching the specified commit email address, and:
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
which allows mailmap to replace both the name and the email of a commit matching both the specified commit name and email address.
Both E-Mails and names are matched case-insensitively. For example this would also match the Commit Name <commit@email.xx> above:
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
Git does not follow symbolic links when accessing a .mailmap file in the working tree. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem.
Your history contains commits by two authors, Jane and Joe, whose names appear in the repository under several forms:
Joe Developer <joe@example.com> Joe R. Developer <joe@example.com> Jane Doe <jane@example.com> Jane Doe <jane@laptop.(none)> Jane D. <jane@desktop.(none)>
Now suppose that Joe wants his middle name initial used, and Jane prefers her family name fully spelled out. A .mailmap file to correct the names would look like:
Joe R. Developer <joe@example.com> Jane Doe <jane@example.com> Jane Doe <jane@desktop.(none)>
Note that there's no need to map the name for <jane@laptop.(none)> to only correct the names. However, leaving the obviously broken <jane@laptop.(none)> and <jane@desktop.(none)> E-Mails as-is is usually not what you want. A .mailmap file which also corrects those is:
Joe R. Developer <joe@example.com> Jane Doe <jane@example.com> <jane@laptop.(none)> Jane Doe <jane@example.com> <jane@desktop.(none)>
Finally, let's say that Joe and Jane shared an E-Mail address, but not a name, e.g. by having these two commits in the history generated by a bug reporting system. I.e. names appearing in history as:
Joe <bugs@example.com> Jane <bugs@example.com>
A full .mailmap file which also handles those cases (an addition of two lines to the above example) would be:
Joe R. Developer <joe@example.com> Jane Doe <jane@example.com> <jane@laptop.(none)> Jane Doe <jane@example.com> <jane@desktop.(none)> Joe R. Developer <joe@example.com> Joe <bugs@example.com> Jane Doe <jane@example.com> Jane <bugs@example.com>
Part of the the section called “git(1)” suite
The .gitmodules file, located in the top-level directory of a Git working tree, is a text file with a syntax matching the requirements of the section called “git-config(1)”.
The file contains one subsection per submodule, and the subsection value is the name of the submodule. The name is set to the path where the submodule has been added unless it was customized with the --name option of git submodule add. Each submodule section also contains the following required keys:
In addition, there are a number of optional keys:
Defines under what circumstances git status and the diff family show a submodule as modified. The following values are supported:
If this option is also present in the submodule's entry in .git/config of the superproject, the setting there will override the one found in .gitmodules.
Both settings can be overridden on the command line by using the --ignore-submodules option. The git submodule commands are not affected by this setting.
Git does not allow the .gitmodules file within a working tree to be a symbolic link, and will refuse to check out such a tree entry. This keeps behavior consistent when the file is accessed from the index or a tree versus from the filesystem, and helps Git reliably enforce security checks of the file contents.
Consider the following .gitmodules file:
[submodule "libfoo"]
path = include/foo
url = git://foo.com/git/lib.git
[submodule "libbar"]
path = include/bar
url = git://bar.com/git/lib.gitThis defines two submodules, libfoo and libbar. These are expected to be checked out in the paths include/foo and include/bar, and for both submodules a URL is specified which can be used for cloning the submodules.
the section called “git-submodule(1)”, the section called “gitsubmodules(7)”, the section called “git-config(1)”
Part of the the section called “git(1)” suite
Git supports dividing the refs of a single repository into multiple namespaces, each of which has its own branches, tags, and HEAD. Git can expose each namespace as an independent repository to pull from and push to, while sharing the object store, and exposing all the refs to operations such as the section called “git-gc(1)”.
Storing multiple repositories as namespaces of a single repository avoids storing duplicate copies of the same objects, such as when storing multiple branches of the same source. The alternates mechanism provides similar support for avoiding duplicates, but alternates do not prevent duplication between new objects added to the repositories without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to the namespace. For each ref namespace, Git stores the corresponding refs in a directory under refs/namespaces/. For example, GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can also specify namespaces via the --namespace option to the section called “git(1)”.
Note that namespaces which include a / will expand to a hierarchy of namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under refs/namespaces/foo/refs/namespaces/bar/. This makes paths in GIT_NAMESPACE behave hierarchically, so that cloning with GIT_NAMESPACE=foo/bar produces the same result as cloning with GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It also avoids ambiguity with strange namespace paths such as foo/refs/heads/, which could otherwise generate directory/file conflicts within the refs directory.
the section called “git-upload-pack(1)” and the section called “git-receive-pack(1)” rewrite the names of refs as specified by GIT_NAMESPACE. git-upload-pack and git-receive-pack will ignore all references outside the specified namespace.
The smart HTTP server, the section called “git-http-backend(1)”, will pass GIT_NAMESPACE through to the backend programs; see the section called “git-http-backend(1)” for sample configuration to expose repository namespaces as repositories.
For a simple local test, you can use the section called “git-remote-ext(1)”:
git clone ext::'git --namespace=foo %s /tmp/prefixed.git'
The fetch and push protocols are not designed to prevent one side from stealing data from the other repository that was not intended to be shared. If you have private data that you need to protect from a malicious peer, your best option is to store it in another repository. This applies to both clients and servers. In particular, namespaces on a server are not effective for read access control; you should only grant read access to a namespace to clients that you would trust with read access to the entire repository.
The known attack vectors are as follows:
Part of the the section called “git(1)” suite
Remote helper programs are normally not used directly by end users, but they are invoked by Git when it needs to interact with remote repositories Git does not support natively. A given helper will implement a subset of the capabilities documented here. When Git needs to interact with a repository using a remote helper, it spawns the helper as an independent process, sends commands to the helper's standard input, and expects results from the helper's standard output. Because a remote helper runs as an independent process from Git, there is no need to re-link Git to add a new helper, nor any need to link the helper with the implementation of Git.
Every helper must support the "capabilities" command, which Git uses to determine what other commands the helper will accept. Those other commands can be used to discover and update remote refs, transport objects between the object database and the remote repository, and update the local object store.
Git comes with a "curl" family of remote helpers, that handle various transport protocols, such as git-remote-http, git-remote-https, git-remote-ftp and git-remote-ftps. They implement the capabilities fetch, option, and push.
Remote helper programs are invoked with one or (optionally) two arguments. The first argument specifies a remote repository as in Git; it is either the name of a configured remote or a URL. The second argument specifies a URL; it is usually of the form <transport>://<address>, but any arbitrary string is possible. The GIT_DIR environment variable is set up for the remote helper and can be used to determine where to store additional data or from which directory to invoke auxiliary Git commands.
When Git encounters a URL of the form <transport>://<address>, where <transport> is a protocol that it cannot handle natively, it automatically invokes git remote-<transport> with the full URL as the second argument. If such a URL is encountered directly on the command line, the first argument is the same as the second, and if it is encountered in a configured remote, the first argument is the name of that remote.
A URL of the form <transport>::<address> explicitly instructs Git to invoke git remote-<transport> with <address> as the second argument. If such a URL is encountered directly on the command line, the first argument is <address>, and if it is encountered in a configured remote, the first argument is the name of that remote.
Additionally, when a configured remote has remote.<name>.vcs set to <transport>, Git explicitly invokes git remote-<transport> with <name> as the first argument. If set, the second argument is remote.<name>.url; otherwise, the second argument is omitted.
Git sends the remote helper a list of commands on standard input, one per line. The first command is always the capabilities command, in response to which the remote helper must print a list of the capabilities it supports (see below) followed by a blank line. The response to the capabilities command determines what commands Git uses in the remainder of the command stream.
The command stream is terminated by a blank line. In some cases (indicated in the documentation of the relevant commands), this blank line is followed by a payload in some other protocol (e.g., the pack protocol), while in others it indicates the end of input.
Each remote helper is expected to support only a subset of commands. The operations a helper supports are declared to Git in the response to the capabilities command (see COMMANDS, below).
In the following, we list all defined capabilities and for each we list which commands a helper with that capability must provide.
Can attempt to connect to git receive-pack (for pushing), git upload-pack, etc for communication using git's native packfile protocol. This requires a bidirectional, full-duplex connection.
Supported commands: connect.
Experimental; for internal use only. Can attempt to connect to a remote server for communication using git's wire-protocol version 2. See the documentation for the stateless-connect command for more information.
Supported commands: stateless-connect.
Can discover remote refs and push local commits and the history leading up to them to new or existing remote refs.
Supported commands: list for-push, push.
Can discover remote refs and push specified objects from a fast-import stream to remote refs.
Supported commands: list for-push, export.
If a helper advertises connect, Git will use it if possible and fall back to another capability if the helper requests so when connecting (see the connect command under COMMANDS). When choosing between push and export, Git prefers push. Other frontends may have some other order of preference.
Can try to connect to git upload-pack (for fetching), git receive-pack, etc for communication using the Git's native packfile protocol. This requires a bidirectional, full-duplex connection.
Supported commands: connect.
Experimental; for internal use only. Can attempt to connect to a remote server for communication using git's wire-protocol version 2. See the documentation for the stateless-connect command for more information.
Supported commands: stateless-connect.
Can discover remote refs and transfer objects reachable from them to the local object store.
Supported commands: list, fetch.
Can discover remote refs and output objects reachable from them as a stream in fast-import format.
Supported commands: list, import.
If a helper advertises connect, Git will use it if possible and fall back to another capability if the helper requests so when connecting (see the connect command under COMMANDS). When choosing between fetch and import, Git prefers fetch. Other frontends may have some other order of preference.
For remote helpers that implement import or export, this capability allows the refs to be constrained to a private namespace, instead of writing to refs/heads or refs/remotes directly. It is recommended that all importers providing the import capability use this. It's mandatory for export.
A helper advertising the capability refspec refs/heads/*:refs/svn/origin/branches/* is saying that, when it is asked to import refs/heads/topic, the stream it outputs will update the refs/svn/origin/branches/topic ref.
This capability can be advertised multiple times. The first applicable refspec takes precedence. The left-hand of refspecs advertised with this capability must cover all refs reported by the list command. If no refspec capability is advertised, there is an implied refspec *:*.
When writing remote-helpers for decentralized version control systems, it is advised to keep a local copy of the repository to interact with, and to let the private namespace refs point to this local repository, while the refs/remotes namespace is used to track the remote repository.
Commands are given by the caller on the helper's standard input, one per line.
Lists the capabilities of the helper, one per line, ending with a blank line. Each capability may be preceded with *, which marks them mandatory for Git versions using the remote helper to understand. Any unknown mandatory capability is a fatal error.
Support for this command is mandatory.
Lists the refs, one per line, in the format "<value> <name> [<attr> …]". The value may be a hex sha1 hash, "@<dest>" for a symref, ":<keyword> <value>" for a key-value pair, or "?" to indicate that the helper could not get the value of the ref. A space-separated list of attributes follows the name; unrecognized attributes are ignored. The list ends with a blank line.
See REF LIST ATTRIBUTES for a list of currently defined attributes. See REF LIST KEYWORDS for a list of currently defined keywords.
Supported if the helper has the "fetch" or "import" capability.
Similar to list, except that it is used if and only if the caller wants to the resulting ref list to prepare push commands. A helper supporting both push and fetch can use this to distinguish for which operation the output of list is going to be used, possibly reducing the amount of work that needs to be performed.
Supported if the helper has the "push" or "export" capability.
Sets the transport helper option <name> to <value>. Outputs a single line containing one of ok (option successfully set), unsupported (option not recognized) or error <msg> (option <name> is supported but <value> is not valid for it). Options should be set before other commands, and may influence the behavior of those commands.
See OPTIONS for a list of currently defined options.
Supported if the helper has the "option" capability.
Fetches the given object, writing the necessary objects to the database. Fetch commands are sent in a batch, one per line, terminated with a blank line. Outputs a single blank line when all fetch commands in the same batch are complete. Only objects which were reported in the output of list with a sha1 may be fetched this way.
Optionally may output a lock <file> line indicating the full path of a file under $GIT_DIR/objects/pack which is keeping a pack until refs can be suitably updated. The path must end with .keep. This is a mechanism to name a <pack,idx,keep> tuple by giving only the keep component. The kept pack will not be deleted by a concurrent repack, even though its objects may not be referenced until the fetch completes. The .keep file will be deleted at the conclusion of the fetch.
If option check-connectivity is requested, the helper must output connectivity-ok if the clone is self-contained and connected.
Supported if the helper has the "fetch" capability.
Pushes the given local <src> commit or branch to the remote branch described by <dst>. A batch sequence of one or more push commands is terminated with a blank line (if there is only one reference to push, a single push command is followed by a blank line). For example, the following would be two batches of push, the first asking the remote-helper to push the local ref master to the remote ref master and the local HEAD to the remote branch, and the second asking to push ref foo to ref bar (forced update requested by the +).
push refs/heads/master:refs/heads/master push HEAD:refs/heads/branch \n push +refs/heads/foo:refs/heads/bar \n
Zero or more protocol options may be entered after the last push command, before the batch's terminating blank line.
When the push is complete, outputs one or more ok <dst> or error <dst> <why>? lines to indicate success or failure of each pushed ref. The status report output is terminated by a blank line. The option field <why> may be quoted in a C style string if it contains an LF.
Supported if the helper has the "push" capability.
Produces a fast-import stream which imports the current value of the named ref. It may additionally import other refs as needed to construct the history efficiently. The script writes to a helper-specific private namespace. The value of the named ref should be written to a location in this namespace derived by applying the refspecs from the "refspec" capability to the name of the ref.
Especially useful for interoperability with a foreign versioning system.
Just like push, a batch sequence of one or more import is terminated with a blank line. For each batch of import, the remote helper should produce a fast-import stream terminated by a done command.
Note that if the bidi-import capability is used the complete batch sequence has to be buffered before starting to send data to fast-import to prevent mixing of commands and fast-import responses on the helper's stdin.
Supported if the helper has the "import" capability.
Instructs the remote helper that any subsequent input is part of a fast-import stream (generated by git fast-export) containing objects which should be pushed to the remote.
Especially useful for interoperability with a foreign versioning system.
The export-marks and import-marks capabilities, if specified, affect this command in so far as they are passed on to git fast-export, which then will load/store a table of marks for local objects. This can be used to implement for incremental operations.
Supported if the helper has the "export" capability.
Connects to given service. Standard input and standard output of helper are connected to specified service (git prefix is included in service name so e.g. fetching uses git-upload-pack as service) on remote side. Valid replies to this command are empty line (connection established), fallback (no smart transport support, fall back to dumb transports) and just exiting with error message printed (can't connect, don't bother trying to fall back). After line feed terminating the positive (empty) response, the output of service starts. After the connection ends, the remote helper exits.
Supported if the helper has the "connect" capability.
Experimental; for internal use only. Connects to the given remote service for communication using git's wire-protocol version 2. Valid replies to this command are empty line (connection established), fallback (no smart transport support, fall back to dumb transports) and just exiting with error message printed (can't connect, don't bother trying to fall back). After line feed terminating the positive (empty) response, the output of the service starts. Messages (both request and response) must consist of zero or more PKT-LINEs, terminating in a flush packet. Response messages will then have a response end packet after the flush packet to indicate the end of a response. The client must not expect the server to store any state in between request-response pairs. After the connection ends, the remote helper exits.
Supported if the helper has the "stateless-connect" capability.
If a fatal error occurs, the program writes the error message to stderr and exits. The caller should expect that a suitable error message has been printed if the child closes the connection without completing a valid response for the current command.
Additional commands may be supported, as may be determined from capabilities reported by the helper.
The list command produces a list of refs in which each ref may be followed by a list of attributes. The following ref list attributes are defined.
The list command may produce a list of key-value pairs. The following keys are defined.
The following options are defined and (under suitable circumstances) set by Git if the remote helper has the option capability.
the section called “git-remote(1)”
the section called “git-remote-ext(1)”
Part of the the section called “git(1)” suite
A Git repository comes in two different flavours:
Note: Also you can have a plain text file .git at the root of your working tree, containing gitdir: <path> to point at the real directory that has the repository. This mechanism is called a gitfile and is usually managed via the git submodule and git worktree commands. It is often used for a working tree of a submodule checkout, to allow you in the containing superproject to git checkout a branch that does not have the submodule. The checkout has to remove the entire submodule working tree, without losing the submodule repository.
These things may exist in a Git repository.
Object store associated with this repository. Usually an object store is self sufficient (i.e. all the objects that are referred to by an object found in it are also found in it), but there are a few ways to violate it.
You could be using the objects/info/alternates or $GIT_ALTERNATE_OBJECT_DIRECTORIES mechanisms to borrow objects from other object stores. A repository with this kind of incomplete object store is not suitable to be published for use with dumb transports but otherwise is OK as long as objects/info/alternates points at the object stores it borrows from.
This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/objects" will be used instead.
A symref (see glossary) to the refs/heads/ namespace describing the currently active branch. It does not mean much if the repository is not associated with any working tree (i.e. a bare repository), but a valid Git repository must have the HEAD file; some porcelains may use it to guess the designated "default" branch of the repository (usually master). It is legal if the named branch name does not (yet) exist. In some legacy setups, it is a symbolic link instead of a symref that points at the current branch.
HEAD can also record a specific commit directly, instead of being a symref to point at the current branch. Such a state is often called detached HEAD. See the section called “git-checkout(1)” for details.
A deprecated way to store shorthands to be used to specify a URL to git fetch, git pull and git push. A file can be stored as branches/<name> and then name can be given to these commands in place of repository argument. See the REMOTES section in the section called “git-fetch(1)” for details. This mechanism is legacy and not likely to be found in modern repositories. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/branches" will be used instead.
Git will stop reading remotes from this directory in Git 3.0.
This file records fake commit ancestry information, to pretend the set of parents a commit has is different from how the commit was actually created. One record per line describes a commit and its fake parents by listing their 40-byte hexadecimal object names separated by a space and terminated by a newline.
Note that the grafts mechanism is outdated and can lead to problems transferring objects between repositories; see the section called “git-replace(1)” for a more flexible and robust system to do the same thing.
Stores shorthands for URL and default refnames for use when interacting with remote repositories via git fetch, git pull and git push commands. See the REMOTES section in the section called “git-fetch(1)” for details. This mechanism is legacy and not likely to be found in modern repositories. This directory is ignored if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/remotes" will be used instead.
Git will stop reading remotes from this directory in Git 3.0.
Every git repository is marked with a numeric version in the core.repositoryformatversion key of its config file. This version specifies the rules for operating on the on-disk repository data. An implementation of git which does not understand a particular version advertised by an on-disk repository MUST NOT operate on that repository; doing so risks not only producing wrong results, but actually losing data.
Because of this rule, version bumps should be kept to an absolute minimum. Instead, we generally prefer these strategies:
A whole-repository format version bump should only be part of a change that cannot be independently versioned. For instance, if one were to change the reachability rules for objects, or the rules for locking refs, that would require a bump of the repository format version.
Note that this applies only to accessing the repository's disk contents directly. An older client which understands only format 0 may still connect via git:// to a repository using format 1, as long as the server process understands format 1.
The preferred strategy for rolling out a version bump (whether whole repository or for a single file) is to teach git to read the new format, and allow writing the new format with a config switch or command line option (for experimentation or for those who do not care about backwards compatibility with older gits). Then after a long period to allow the reading capability to become common, we may switch to writing the new format by default.
The currently defined format versions are:
This is the format defined by the initial version of git, including but not limited to the format of the repository directory, the repository configuration file, and the object and ref storage. Specifying the complete behavior of git is beyond the scope of this document.
This format is identical to version 0, with the following exceptions:
Note that if no extensions are specified in the config file, then core.repositoryformatversion SHOULD be set to 0 (setting it to 1 provides no benefit, and makes the repository incompatible with older implementations of git).
The defined extensions are given in the extensions.* section of the section called “git-config(1)”. Any implementation wishing to define a new extension should make a note of it there, in order to claim the name.
the section called “git-init(1)”, the section called “git-clone(1)”, the section called “git-config(1)”, the section called “git-fetch(1)”, the section called “git-pack-refs(1)”, the section called “git-gc(1)”, the section called “git-checkout(1)”, the section called “gitglossary(7)”, The Git User's Manual
Part of the the section called “git(1)” suite
Many Git commands take revision parameters as arguments. Depending on the command, they denote a specific commit or, for commands which walk the revision graph (such as the section called “git-log(1)”), all commits which are reachable from that commit. For commands that walk the revision graph one can also specify a range of revisions explicitly.
In addition, some Git commands (such as the section called “git-show(1)” and the section called “git-push(1)”) can also take revision parameters which denote other objects than commits, e.g. blobs ("files") or trees ("directories of files").
A revision parameter <rev> typically, but not necessarily, names a commit object. It uses what is called an extended SHA-1 syntax. Here are various ways to spell object names. The ones listed near the end of this list name trees and blobs contained in a commit.
This document shows the "raw" syntax as seen by git. The shell and other UIs might require additional quoting to protect special characters and to avoid word splitting.
A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:
Note that any of the refs/* cases above may come either from the $GIT_DIR/refs directory or from the $GIT_DIR/packed-refs file. While the ref name encoding is unspecified, UTF-8 is preferred as some output processing may assume ref names in UTF-8.
The suffix @{push} reports the branch "where we would push to" if git push were run while branchname was checked out (or the current HEAD if no branchname is specified). Like for @{upstream}, we report the remote-tracking branch that corresponds to that branch at the remote.
Here's an example to make it more clear:
$ git config push.default current
$ git config remote.pushdefault myfork
$ git switch -c mybranch origin/master
$ git rev-parse --symbolic-full-name @{upstream}
refs/remotes/origin/master
$ git rev-parse --symbolic-full-name @{push}
refs/remotes/myfork/mybranchNote in the example that we set up a triangular workflow, where we pull from one location and push to another. In a non-triangular workflow, @{push} is the same as @{upstream}, and there is no need for it.
This suffix is also accepted when spelled in uppercase, and means the same thing no matter the case.
A suffix ^ followed by an object type name enclosed in brace pair means dereference the object at <rev> recursively until an object of type <type> is found or the object cannot be dereferenced anymore (in which case, barf). For example, if <rev> is a commit-ish, <rev>^{commit} describes the corresponding commit object. Similarly, if <rev> is a tree-ish, <rev>^{tree} describes the corresponding tree object. <rev>^0 is a short-hand for <rev>^{commit}.
<rev>^{object} can be used to make sure <rev> names an object that exists, without requiring <rev> to be a tag, and without dereferencing <rev>; because a tag is already an object, it does not have to be dereferenced even once to get to an object.
<rev>^{tag} can be used to ensure that <rev> identifies an existing tag object.
Here is an illustration, by Jon Loeliger. Both commit nodes B and C are parents of commit node A. Parent commits are ordered left-to-right.
G H I J
\ / \ /
D E F
\ | / \
\ | / |
\|/ |
B C
\ /
\ /
AA = = A^0 B = A^ = A^1 = A~1 C = = A^2 D = A^^ = A^1^1 = A~2 E = B^2 = A^^2 F = B^3 = A^^3 G = A^^^ = A^1^1^1 = A~3 H = D^2 = B^^2 = A^^^2 = A~2^2 I = F^ = B^3^ = A^^3^ J = F^2 = B^3^2 = A^^3^2
History traversing commands such as git log operate on a set of commits, not just a single commit.
For these commands, specifying a single revision, using the notation described in the previous section, means the set of commits reachable from the given commit.
Specifying several revisions means the set of commits reachable from any of the given commits.
A commit's reachable set is the commit itself and the commits in its ancestry chain.
There are several notations to specify a set of connected commits (called a "revision range"), illustrated below.
In these two shorthand notations, you can omit one end and let it default to HEAD. For example, origin.. is a shorthand for origin..HEAD and asks "What did I do since I forked from the origin branch?" Similarly, ..origin is a shorthand for HEAD..origin and asks "What did the origin do since I forked from them?" Note that .. would mean HEAD..HEAD which is an empty range that is both reachable and unreachable from HEAD.
Commands that are specifically designed to take two distinct ranges (e.g. "git range-diff R1 R2" to compare two ranges) do exist, but they are exceptions. Unless otherwise noted, all "git" commands that operate on a set of commits work on a single revision range. In other words, writing two "two-dot range notation" next to each other, e.g.
$ git log A..B C..D
does not specify two revision ranges for most commands. Instead it will name a single connected set of commits, i.e. those that are reachable from either B or D but are reachable from neither A or C. In a linear history like this:
---A---B---o---o---C---D
because A and B are reachable from C, the revision range specified by these two dotted ranges is a single commit D.
Three other shorthands exist, particularly useful for merge commits, for naming a set that is formed by a commit and its parent commits.
The r1^@ notation means all parents of r1.
The r1^! notation includes commit r1 but excludes all of its parents. By itself, this notation denotes the single commit r1.
The <rev>^-[<n>] notation includes <rev> but excludes the <n>th parent (i.e. a shorthand for <rev>^<n>..<rev>), with <n> = 1 if not given. This is typically useful for merge commits where you can just pass <commit>^- to get all the commits in the branch that was merged in merge commit <commit> (including <commit> itself).
While <rev>^<n> was about specifying a single commit parent, these three notations also consider its parents. For example you can say HEAD^2^@, however you cannot say HEAD^@^2.
Here are a handful of examples using the Loeliger illustration above, with each step in the notation's expansion and selection carefully spelt out:
Args Expanded arguments Selected commits
D G H D
D F G H I J D F
^G D H D
^D B E I J F B
^D B C E I J F B C
C I J F C
B..C = ^B C C
B...C = B ^F C G H D E B C
B^- = B^..B
= ^B^1 B E I J F B
C^@ = C^1
= F I J F
B^@ = B^1 B^2 B^3
= D E F D G H E F I J
C^! = C ^C^@
= C ^C^1
= C ^F C
B^! = B ^B^@
= B ^B^1 ^B^2 ^B^3
= B ^D ^E ^F B
F^! D = F ^I ^J D G H D FPart of the the section called “git(1)” suite
A submodule is a repository embedded inside another repository. The submodule has its own history; the repository it is embedded in is called a superproject.
On the filesystem, a submodule usually (but not always - see FORMS below) consists of (i) a Git directory located under the $GIT_DIR/modules/ directory of its superproject, (ii) a working directory inside the superproject's working directory, and a .git file at the root of the submodule's working directory pointing to (i).
Assuming the submodule has a Git directory at $GIT_DIR/modules/foo/ and a working directory at path/to/bar/, the superproject tracks the submodule via a gitlink entry in the tree at path/to/bar and an entry in its .gitmodules file (see the section called “gitmodules(5)”) of the form submodule.foo.path = path/to/bar.
The gitlink entry contains the object name of the commit that the superproject expects the submodule's working directory to be at.
The section submodule.foo.* in the .gitmodules file gives additional hints to Git's porcelain layer. For example, the submodule.foo.url setting specifies where to obtain the submodule.
Submodules can be used for at least two different use cases:
Splitting a (logically single) project into multiple repositories and tying them back together. This can be used to overcome current limitations of Git's implementation to have finer grained access:
Submodule operations can be configured using the following mechanisms (from highest to lowest precedence):
The configuration inside the submodule. This includes $GIT_DIR/config in the submodule, but also settings in the tree such as a .gitattributes or .gitignore files that specify behavior of commands inside the submodule.
For example an effect from the submodule's .gitignore file would be observed when you run git status --ignore-submodules=none in the superproject. This collects information from the submodule's working directory by running status in the submodule while paying attention to the .gitignore file of the submodule.
The submodule's $GIT_DIR/config file would come into play when running git push --recurse-submodules=check in the superproject, as this would check if the submodule has any changes not published to any remote. The remotes are configured in the submodule as usual in the $GIT_DIR/config file.
The configuration file $GIT_DIR/config in the superproject. Git only recurses into active submodules (see "ACTIVE SUBMODULES" section below).
If the submodule is not yet initialized, then the configuration inside the submodule does not exist yet, so where to obtain the submodule from is configured here for example.
The .gitmodules file inside the superproject. A project usually uses this file to suggest defaults for the upstream collection of repositories for the mapping that is required between a submodule's name and its path.
This file mainly serves as the mapping between the name and path of submodules in the superproject, such that the submodule's Git directory can be located.
If the submodule has never been initialized, this is the only place where submodule configuration is found. It serves as the last fallback to specify where to obtain the submodule from.
Submodules can take the following forms:
"Old-form" submodule: A working directory with an embedded .git directory, and the tracking gitlink and .gitmodules entry in the superproject. This is typically found in repositories generated using older versions of Git.
It is possible to construct these old form repositories manually.
When deinitialized or deleted (see below), the submodule's Git directory is automatically moved to $GIT_DIR/modules/<name>/ of the superproject.
Deinitialized submodule: A gitlink, and a .gitmodules entry, but no submodule working directory. The submodule's Git directory may be there as after deinitializing the Git directory is kept around. The directory which is supposed to be the working directory is empty instead.
A submodule can be deinitialized by running git submodule deinit. Besides emptying the working directory, this command only modifies the superproject's $GIT_DIR/config file, so the superproject's history is not affected. This can be undone using git submodule init.
Deleted submodule: A submodule can be deleted by running git rm <submodule-path> && git commit. This can be undone using git revert.
The deletion removes the superproject's tracking data, which are both the gitlink entry and the section in the .gitmodules file. The submodule's working directory is removed from the file system, but the Git directory is kept around as it to make it possible to checkout past commits without requiring fetching from another repository.
To completely remove a submodule, manually delete $GIT_DIR/modules/<name>/.
A submodule is considered active,
if submodule.<name>.active is set to true
or
if the submodule's path matches the pathspec in submodule.active
or
and these are evaluated in this order.
For example:
[submodule "foo"] active = false url = https://example.org/foo [submodule "bar"] active = true url = https://example.org/bar [submodule "baz"] url = https://example.org/baz
In the above config only the submodules bar and baz are active, bar due to (1) and baz due to (3). foo is inactive because (1) takes precedence over (3)
Note that (3) is a historical artefact and will be ignored if the (1) and (2) specify that the submodule is not active. In other words, if we have a submodule.<name>.active set to false or if the submodule's path is excluded in the pathspec in submodule.active, the url doesn't matter whether it is present or not. This is illustrated in the example that follows.
[submodule "foo"] active = true url = https://example.org/foo [submodule "bar"] url = https://example.org/bar [submodule "baz"] url = https://example.org/baz [submodule "bob"] ignore = true [submodule] active = b* active = :(exclude) baz
In here all submodules except baz (foo, bar, bob) are active. foo due to its own active flag and all the others due to the submodule active pathspec, which specifies that any submodule starting with b except baz are also active, regardless of the presence of the .url field.
# Add a submodule git submodule add <URL> <path>
# Occasionally update the submodule to a new version: git -C <path> checkout <new-version> git add <path> git commit -m "update submodule to new version"
# See the list of submodules in a superproject git submodule status
# See FORMS on removing submodules
# Enable recursion for relevant commands, such that # regular commands recurse into submodules by default git config --global submodule.recurse true
# Unlike most other commands below, clone still needs # its own recurse flag: git clone --recurse <URL> <directory> cd <directory>
# Get to know the code: git grep foo git ls-files --recurse-submodules
git ls-files also requires its own --recurse-submodules flag.
# Get new code git fetch git pull --rebase
# Change worktree git checkout git reset
When cloning or pulling a repository containing submodules the submodules will not be checked out by default; you can instruct clone to recurse into submodules. The init and update subcommands of git submodule will maintain submodules checked out and at an appropriate revision in your working tree. Alternatively you can set submodule.recurse to have checkout recurse into submodules (note that submodule.recurse also affects other Git commands, see the section called “git-config(1)” for a complete list).
Part of the the section called “git(1)” suite
To get started with gitweb, run the section called “git-instaweb(1)” from a Git repository. This will configure and start your web server, and run a web browser pointing to gitweb.
Gitweb provides a web interface to Git repositories. Its features include:
See https://repo.or.cz/w/git.git/tree/HEAD:/gitweb/ for gitweb source code, browsed using gitweb itself.
Various aspects of gitweb's behavior can be controlled through the configuration file gitweb_config.perl or /etc/gitweb.conf. See the the section called “gitweb.conf(5)” for details.
Gitweb can show information from one or more Git repositories. These repositories have to be all on local filesystem, and have to share a common repository root, i.e. be all under a single parent repository (but see also the "Advanced web server setup" section, "Webserver configuration with multiple projects' root" subsection).
our $projectroot = '/path/to/parent/directory';
The default value for $projectroot is /pub/git. You can change it during building gitweb via the GITWEB_PROJECTROOT build configuration variable.
By default all Git repositories under $projectroot are visible and available to gitweb. The list of projects is generated by default by scanning the $projectroot directory for Git repositories (for object databases to be more exact; gitweb is not interested in a working area, and is best suited to showing "bare" repositories).
The name of the repository in gitweb is the path to its $GIT_DIR (its object database) relative to $projectroot. Therefore the repository $repo can be found at "$projectroot/$repo".
Instead of having gitweb find repositories by scanning the filesystem starting from $projectroot, you can provide a pre-generated list of visible projects by setting $projects_list to point to a plain text file with a list of projects (with some additional info).
This file uses the following format:
Fields use modified URI encoding, defined in RFC 3986, section 2.1 (Percent-Encoding), or rather "Query string encoding" (see https://en.wikipedia.org/wiki/Query_string#URL_encoding), the difference being that SP (" ") can be encoded as "+" (and therefore "+" has to be also percent-encoded).
Reserved characters are: "%" (used for encoding), "+" (can be used to encode SPACE), all whitespace characters as defined in Perl, including SP, TAB and LF, (used to separate fields in a record).
Currently recognized fields are:
You can generate the projects list index file using the project_index action (the TXT link on projects list page) directly from gitweb; see also "Generating projects list using gitweb" section below.
Example contents:
foo.git Joe+R+Hacker+<joe@example.com> foo/bar.git O+W+Ner+<owner@example.org>
By default this file controls only which projects are visible on projects list page (note that entries that do not point to correctly recognized Git repositories won't be displayed by gitweb). Even if a project is not visible on projects list page, you can view it nevertheless by hand-crafting a gitweb URL. By setting $strict_export configuration variable (see the section called “gitweb.conf(5)”) to true value you can allow viewing only of repositories also shown on the overview page (i.e. only projects explicitly listed in projects list file will be accessible).
We assume that GITWEB_CONFIG has its default Makefile value, namely gitweb_config.perl. Put the following in gitweb_make_index.perl file:
read_config_file("gitweb_config.perl");
$projects_list = $projectroot;Then create the following script to get list of project in the format suitable for GITWEB_LIST build configuration variable (or $projects_list variable in gitweb config):
#!/bin/sh export GITWEB_CONFIG="gitweb_make_index.perl" export GATEWAY_INTERFACE="CGI/1.1" export HTTP_ACCEPT="*/*" export REQUEST_METHOD="GET" export QUERY_STRING="a=project_index" perl -- /var/www/cgi-bin/gitweb.cgi
Run this script and save its output to a file. This file could then be used as projects list file, which means that you can set $projects_list to its filename.
By default all Git repositories under $projectroot are visible and available to gitweb. You can however configure how gitweb controls access to repositories.
You can configure gitweb to only list and allow viewing of the explicitly exported repositories, via $export_ok variable in gitweb config file; see the section called “gitweb.conf(5)” manpage. If it evaluates to true, gitweb shows repositories only if this file named by $export_ok exists in its object database (if directory has the magic file named $export_ok).
For example the section called “git-daemon(1)” by default (unless --export-all option is used) allows pulling only for those repositories that have git-daemon-export-ok file. Adding
our $export_ok = "git-daemon-export-ok";
makes gitweb show and allow access only to those repositories that can be fetched from via git:// protocol.
Finally, it is possible to specify an arbitrary perl subroutine that will be called for each repository to determine if it can be exported. The subroutine receives an absolute path to the project (repository) as its only parameter (i.e. "$projectroot/$project").
For example, if you use mod_perl to run the script, and have dumb HTTP protocol authentication configured for your repositories, you can use the following hook to allow access only if the user is authorized to read the files:
$export_auth_hook = sub {
use Apache2::SubRequest ();
use Apache2::Const -compile => qw(HTTP_OK);
my $path = "$_[0]/HEAD";
my $r = Apache2::RequestUtil->request;
my $sub = $r->lookup_file($path);
return $sub->filename eq $path
&& $sub->status == Apache2::Const::HTTP_OK;
};You can configure individual repositories shown in gitweb by creating file in the GIT_DIR of Git repository, or by setting some repo configuration variable (in GIT_DIR/config, see the section called “git-config(1)”).
You can use the following files in repository:
Short (shortened to $projects_list_description_width in the projects list page, which is 25 characters by default; see the section called “gitweb.conf(5)”) single line description of a project (of a repository). Plain text file; HTML will be escaped. By default set to
Unnamed repository; edit this file to name it for gitweb.
from the template during repository creation, usually installed in /usr/share/git-core/templates/. You can use the gitweb.description repo configuration variable, but the file takes precedence.
Single line category of a project, used to group projects if $projects_list_group_categories is enabled. By default (file and configuration variable absent), uncategorized projects are put in the $project_list_default_category category. You can use the gitweb.category repo configuration variable, but the file takes precedence.
The configuration variables $projects_list_group_categories and $project_list_default_category are described in the section called “gitweb.conf(5)”
File with repository URL (used for clone and fetch), one per line. Displayed in the project summary page. You can use multiple-valued gitweb.url repository configuration variable for that, but the file takes precedence.
This is per-repository enhancement / version of global prefix-based @git_base_url_list gitweb configuration variable (see the section called “gitweb.conf(5)”).
You can use the gitweb.owner repository configuration variable to set repository's owner. It is displayed in the project list and summary page.
If it's not set, filesystem directory's owner is used (via GECOS field, i.e. real name field from getpwuid(3)) if $projects_list is unset (gitweb scans $projectroot for repositories); if $projects_list points to file with list of repositories, then project owner defaults to value from this file for given repository.
Gitweb can use path_info (component) based URLs, or it can pass all necessary information via query parameters. The typical gitweb URLs are broken down in to five components:
.../gitweb.cgi/<repo>/<action>/<revision>:/<path>?<arguments>
The repository the action will be performed on.
All actions except for those that list all available projects, in whatever form, require this parameter.
Some actions require or allow to specify two revisions, and sometimes even two pathnames. In most general form such path_info (component) based gitweb URL looks like this:
.../gitweb.cgi/<repo>/<action>/<revision-from>:/<path-from>..<revision-to>:/<path-to>?<arguments>
Each action is implemented as a subroutine, and must be present in %actions hash. Some actions are disabled by default, and must be turned on via feature mechanism. For example to enable blame view add the following to gitweb configuration file:
$feature{'blame'}{'default'} = [1];The standard actions are:
Lists all local or all remote-tracking branches in given repository.
The latter is not available by default, unless configured.
Shows the blame (also called annotation) information for a file. On a per line basis it shows the revision in which that line was last changed and the user that committed the change. The incremental version (which if configured is used automatically when JavaScript is enabled) uses Ajax to incrementally add blame info to the contents of given file.
This action is disabled by default for performance reasons.
Shows log information (commit message or just commit subject) for a given branch (starting from given revision).
The shortlog view is more compact; it shows one commit per line.
Shows history of the file or directory in a given repository path, starting from given revision (defaults to HEAD, i.e. default branch).
This view is similar to shortlog view.
This section explains how to configure some common webservers to run gitweb. In all cases, /path/to/gitweb in the examples is the directory you ran installed gitweb in, and contains gitweb_config.perl.
If you've configured a web server that isn't listed here for gitweb, please send in the instructions so they can be included in a future release.
Apache must be configured to support CGI scripts in the directory in which gitweb is installed. Let's assume that it is /var/www/cgi-bin directory.
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<Directory "/var/www/cgi-bin">
Options Indexes FollowSymlinks ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>With that configuration the full path to browse repositories would be:
http://server/cgi-bin/gitweb.cgi
You can use mod_perl with gitweb. You must install Apache::Registry (for mod_perl 1.x) or ModPerl::Registry (for mod_perl 2.x) to enable this support.
Assuming that gitweb is installed to /var/www/perl, the following Apache configuration (for mod_perl 2.x) is suitable.
Alias /perl "/var/www/perl"
<Directory "/var/www/perl">
SetHandler perl-script
PerlResponseHandler ModPerl::Registry
PerlOptions +ParseHeaders
Options Indexes FollowSymlinks +ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>With that configuration the full path to browse repositories would be:
http://server/perl/gitweb.cgi
Gitweb works with Apache and FastCGI. First you need to rename, copy or symlink gitweb.cgi to gitweb.fcgi. Let's assume that gitweb is installed in /usr/share/gitweb directory. The following Apache configuration is suitable (UNTESTED!)
FastCgiServer /usr/share/gitweb/gitweb.cgi
ScriptAlias /gitweb /usr/share/gitweb/gitweb.cgi
Alias /gitweb/static /usr/share/gitweb/static
<Directory /usr/share/gitweb/static>
SetHandler default-handler
</Directory>With that configuration the full path to browse repositories would be:
http://server/gitweb
All of those examples use request rewriting, and need mod_rewrite (or equivalent; examples below are written for Apache).
If you want to have one URL for both gitweb and your http:// repositories, you can configure Apache like this:
<VirtualHost *:80>
ServerName git.example.org
DocumentRoot /pub/git
SetEnv GITWEB_CONFIG /etc/gitweb.conf
# turning on mod rewrite
RewriteEngine on
# make the front page an internal rewrite to the gitweb script
RewriteRule ^/$ /cgi-bin/gitweb.cgi
# make access for "dumb clients" work
RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ \
/cgi-bin/gitweb.cgi%{REQUEST_URI} [L,PT]
</VirtualHost>The above configuration expects your public repositories to live under /pub/git and will serve them as http://git.domain.org/dir-under-pub-git, both as clonable Git URL and as browsable gitweb interface. If you then start your the section called “git-daemon(1)” with --base-path=/pub/git --export-all then you can even use the git:// URL with exactly the same path.
Setting the environment variable GITWEB_CONFIG will tell gitweb to use the named file (i.e. in this example /etc/gitweb.conf) as a configuration for gitweb. You don't really need it in above example; it is required only if your configuration file is in different place than built-in (during compiling gitweb) gitweb_config.perl or /etc/gitweb.conf. See the section called “gitweb.conf(5)” for details, especially information about precedence rules.
If you use the rewrite rules from the example you might also need something like the following in your gitweb configuration file (/etc/gitweb.conf following example):
@stylesheets = ("/some/absolute/path/gitweb.css");
$my_uri = "/";
$home_link = "/";
$per_request_config = 1;Nowadays though gitweb should create HTML base tag when needed (to set base URI for relative links), so it should work automatically.
If you want to use gitweb with several project roots you can edit your Apache virtual host and gitweb configuration files in the following way.
The virtual host configuration (in Apache configuration file) should look like this:
<VirtualHost *:80>
ServerName git.example.org
DocumentRoot /pub/git
SetEnv GITWEB_CONFIG /etc/gitweb.conf
# turning on mod rewrite
RewriteEngine on
# make the front page an internal rewrite to the gitweb script
RewriteRule ^/$ /cgi-bin/gitweb.cgi [QSA,L,PT]
# look for a public_git directory in unix users' home
# http://git.example.org/~<user>/
RewriteRule ^/\~([^\/]+)(/|/gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/home/$1/public_git/,L,PT]
# http://git.example.org/+<user>/
#RewriteRule ^/\+([^\/]+)(/|/gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/home/$1/public_git/,L,PT]
# http://git.example.org/user/<user>/
#RewriteRule ^/user/([^\/]+)/(gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/home/$1/public_git/,L,PT]
# defined list of project roots
RewriteRule ^/scm(/|/gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/pub/scm/,L,PT]
RewriteRule ^/var(/|/gitweb.cgi)?$ /cgi-bin/gitweb.cgi \
[QSA,E=GITWEB_PROJECTROOT:/var/git/,L,PT]
# make access for "dumb clients" work
RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ \
/cgi-bin/gitweb.cgi%{REQUEST_URI} [L,PT]
</VirtualHost>Here actual project root is passed to gitweb via GITWEB_PROJECT_ROOT environment variable from a web server, so you need to put the following line in gitweb configuration file (/etc/gitweb.conf in above example):
$projectroot = $ENV{'GITWEB_PROJECTROOT'} || "/pub/git";Note that this requires to be set for each request, so either $per_request_config must be false, or the above must be put in code referenced by $per_request_config;
These configurations enable two things. First, each unix user (<user>) of the server will be able to browse through gitweb Git repositories found in ~/public_git/ with the following url:
http://git.example.org/~<user>/
If you do not want this feature on your server just remove the second rewrite rule.
If you already use mod_userdir` in your virtual host or you don't want to use the '~ as first character, just comment or remove the second rewrite rule, and uncomment one of the following according to what you want.
Second, repositories found in /pub/scm/ and /var/git/ will be accessible through http://git.example.org/scm/ and http://git.example.org/var/. You can add as many project roots as you want by adding rewrite rules like the third and the fourth.
If you enable PATH_INFO usage in gitweb by putting
$feature{'pathinfo'}{'default'} = [1];in your gitweb configuration file, it is possible to set up your server so that it consumes and produces URLs in the form
http://git.example.com/project.git/shortlog/sometag
i.e. without gitweb.cgi part, by using a configuration such as the following. This configuration assumes that /var/www/gitweb is the DocumentRoot of your webserver, contains the gitweb.cgi script and complementary static files (stylesheet, favicon, JavaScript):
<VirtualHost *:80>
ServerAlias git.example.com
DocumentRoot /var/www/gitweb
<Directory /var/www/gitweb>
Options ExecCGI
AddHandler cgi-script cgi
DirectoryIndex gitweb.cgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.* /gitweb.cgi/$0 [L,PT]
</Directory>
</VirtualHost>The rewrite rule guarantees that existing static files will be properly served, whereas any other URL will be passed to gitweb as PATH_INFO parameter.
Notice that in this case you don't need special settings for @stylesheets, $my_uri and $home_link, but you lose "dumb client" access to your project .git dirs (described in "Single URL for gitweb and for fetching" section). A possible workaround for the latter is the following: in your project root dir (e.g. /pub/git) have the projects named without a .git extension (e.g. /pub/git/project instead of /pub/git/project.git) and configure Apache as follows:
<VirtualHost *:80>
ServerAlias git.example.com
DocumentRoot /var/www/gitweb
AliasMatch ^(/.*?)(\.git)(/.*)?$ /pub/git$1$3
<Directory /var/www/gitweb>
Options ExecCGI
AddHandler cgi-script cgi
DirectoryIndex gitweb.cgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.* /gitweb.cgi/$0 [L,PT]
</Directory>
</VirtualHost>The additional AliasMatch makes it so that
http://git.example.com/project.git
will give raw access to the project's Git dir (so that the project can be cloned), while
http://git.example.com/project
will provide human-friendly gitweb access.
This solution is not 100% bulletproof, in the sense that if some project has a named ref (branch, tag) starting with git/, then paths such as
http://git.example.com/project/command/abranch..git/abranch
will fail with a 404 error.
Please report any bugs or feature requests to git@vger.kernel.org, putting "gitweb" in the subject of email.
the section called “gitweb.conf(5)”, the section called “git-instaweb(1)”
gitweb/README, gitweb/INSTALL
Part of the the section called “git(1)” suite
The gitweb CGI script for viewing Git repositories over the web uses a perl script fragment as its configuration file. You can set variables using "our $variable = value"; text from a "#" character until the end of a line is ignored. See perlsyn(1) for details.
An example:
# gitweb configuration file for http://git.example.org # our $projectroot = "/srv/git"; # FHS recommendation our $site_name = 'Example.org >> Repos';
The configuration file is used to override the default settings that were built into gitweb at the time the gitweb.cgi script was generated.
While one could just alter the configuration settings in the gitweb CGI itself, those changes would be lost upon upgrade. Configuration settings might also be placed into a file in the same directory as the CGI script with the default name gitweb_config.perl -- allowing one to have multiple gitweb instances with different configurations by the use of symlinks.
Note that some configuration can be controlled on per-repository rather than gitweb-wide basis: see "Per-repository gitweb configuration" subsection on the section called “gitweb(1)” manpage.
Gitweb reads configuration data from the following sources in the following order:
Values obtained in later configuration files override values obtained earlier in the above sequence.
Locations of the common system-wide configuration file, the fallback system-wide configuration file and the per-instance configuration file are defined at compile time using build-time Makefile configuration variables, respectively GITWEB_CONFIG_COMMON, GITWEB_CONFIG_SYSTEM and GITWEB_CONFIG.
You can also override locations of gitweb configuration files during runtime by setting the following environment variables: GITWEB_CONFIG_COMMON, GITWEB_CONFIG_SYSTEM and GITWEB_CONFIG to a non-empty value.
The syntax of the configuration files is that of Perl, since these files are handled by sourcing them as fragments of Perl code (the language that gitweb itself is written in). Variables are typically set using the our qualifier (as in "our $variable = <value>;") to avoid syntax errors if a new version of gitweb no longer uses a variable and therefore stops declaring it.
You can include other configuration file using read_config_file() subroutine. For example, one might want to put gitweb configuration related to access control for viewing repositories via Gitolite (one of Git repository management tools) in a separate file, e.g. in /etc/gitweb-gitolite.conf. To include it, put
read_config_file("/etc/gitweb-gitolite.conf");somewhere in gitweb configuration file used, e.g. in per-installation gitweb configuration file. Note that read_config_file() checks itself that the file it reads exists, and does nothing if it is not found. It also handles errors in included file.
The default configuration with no configuration file at all may work perfectly well for some installations. Still, a configuration file is useful for customizing or tweaking the behavior of gitweb in many ways, and some optional features will not be present unless explicitly enabled using the configurable %features variable (see also "Configuring gitweb features" section below).
Some configuration variables have their default values (embedded in the CGI script) set during building gitweb -- if that is the case, this fact is put in their description. See gitweb's INSTALL file for instructions on building and installing gitweb.
The configuration variables described below control how gitweb finds Git repositories, and how repositories are displayed and accessed.
See also "Repositories" and later subsections in the section called “gitweb(1)” manpage.
Absolute filesystem path which will be prepended to project path; the path to repository is $projectroot/$project. Set to $GITWEB_PROJECTROOT during installation. This variable has to be set correctly for gitweb to find repositories.
For example, if $projectroot is set to "/srv/git" by putting the following in gitweb config file:
our $projectroot = "/srv/git";
then
http://git.example.com/gitweb.cgi?p=foo/bar.git
and its path_info based equivalent
http://git.example.com/gitweb.cgi/foo/bar.git
will map to the path /srv/git/foo/bar.git on the filesystem.
Name of a plain text file listing projects, or a name of directory to be scanned for projects.
Project list files should list one project per line, with each line having the following format
<URI-encoded filesystem path to repository> SP <URI-encoded repository owner>
The default value of this variable is determined by the GITWEB_LIST makefile variable at installation time. If this variable is empty, gitweb will fall back to scanning the $projectroot directory for repositories.
If $projects_list variable is unset, gitweb will recursively scan filesystem for Git repositories. The $project_maxdepth is used to limit traversing depth, relative to $projectroot (starting point); it means that directories which are further from $projectroot than $project_maxdepth will be skipped.
It is purely performance optimization, originally intended for MacOS X, where recursive directory traversal is slow. Gitweb follows symbolic links, but it detects cycles, ignoring any duplicate files and directories.
The default value of this variable is determined by the build-time configuration variable GITWEB_PROJECT_MAXDEPTH, which defaults to 2007.
Function used to determine which repositories should be shown. This subroutine should take one parameter, the full path to a project, and if it returns true, that project will be included in the projects list and can be accessed through gitweb as long as it fulfills the other requirements described by $export_ok, $projects_list, and $projects_maxdepth. Example:
our $export_auth_hook = sub { return -e "$_[0]/git-daemon-export-ok"; };though the above might be done by using $export_ok instead
our $export_ok = "git-daemon-export-ok";
If not set (default), it means that this feature is disabled.
See also more involved example in "Controlling access to Git repositories" subsection on the section called “gitweb(1)” manpage.
The following configuration variables tell gitweb where to find files. The values of these variables are paths on the filesystem.
Path to the highlight executable to use (it must be the one from http://andre-simon.de/zip/download.php due to assumptions about parameters and output). By default set to highlight; set it to full path to highlight executable if it is not installed on your web server's PATH. Note that highlight feature must be set for gitweb to actually use syntax highlighting.
NOTE: for a file to be highlighted, its syntax type must be detected and that syntax must be supported by "highlight". The default syntax detection is minimal, and there are many supported syntax types with no detection by default. There are three options for adding syntax detection. The first and second priority are %highlight_basename and %highlight_ext, which detect based on basename (the full filename, for example "Makefile") and extension (for example "sh"). The keys of these hashes are the basename and extension, respectively, and the value for a given key is the name of the syntax to be passed via --syntax <syntax> to "highlight". The last priority is the "highlight" configuration of Shebang regular expressions to detect the language based on the first line in the file, (for example, matching the line "#!/bin/bash"). See the highlight documentation and the default config at /etc/highlight/filetypes.conf for more details.
For example if repositories you are hosting use "phtml" extension for PHP files, and you want to have correct syntax-highlighting for those files, you can add the following to gitweb configuration:
our %highlight_ext;
$highlight_ext{'phtml'} = 'php';The configuration variables described below configure some of gitweb links: their target and their look (text or image), and where to find page prerequisites (stylesheet, favicon, images, scripts). Usually they are left at their default values, with the possible exception of @stylesheets variable.
List of URIs of stylesheets (relative to the base URI of a page). You might specify more than one stylesheet, for example to use "gitweb.css" as base with site specific modifications in a separate stylesheet to make it easier to upgrade gitweb. For example, you can add a site stylesheet by putting
push @stylesheets, "gitweb-site.css";
in the gitweb config file. Those values that are relative paths are relative to base URI of gitweb.
This list should contain the URI of gitweb's standard stylesheet. The default URI of gitweb stylesheet can be set at build time using the GITWEB_CSS makefile variable. Its default value is static/gitweb.css (or static/gitweb.min.css if the CSSMIN variable is defined, i.e. if CSS minifier is used during build).
Note: there is also a legacy $stylesheet configuration variable, which was used by older gitweb. If $stylesheet variable is defined, only CSS stylesheet given by this variable is used by gitweb.
Points to the location where you put gitweb.js on your web server, or to be more generic the URI of JavaScript code used by gitweb. Relative to the base URI of gitweb. Can be set at build time using the GITWEB_JS build-time configuration variable.
The default value is either static/gitweb.js, or static/gitweb.min.js if the JSMIN build variable was defined, i.e. if JavaScript minifier was used at build time. Note that this single file is generated from multiple individual JavaScript "modules".
Additional links to be added to the start of the breadcrumb trail before the home link, to pages that are logically "above" the gitweb projects list, such as the organization and department which host the gitweb server. Each element of the list is a reference to an array, in which element 0 is the link text (equivalent to $home_link_str) and element 1 is the target URL (equivalent to $home_link).
For example, the following setting produces a breadcrumb trail like "home / dev / projects / …" where "projects" is the home link.
our @extra_breadcrumbs = (
[ 'home' => 'https://www.example.org/' ],
[ 'dev' => 'https://dev.example.org/' ],
);You can adjust how pages generated by gitweb look using the variables described below. You can change the site name, add common headers and footers for all pages, and add a description of this gitweb installation on its main page (which is the projects list page), etc.
Name of your site or organization, to appear in page titles. Set it to something descriptive for clearer bookmarks etc. If this variable is not set or is, then gitweb uses the value of the SERVER_NAME CGI environment variable, setting site name to "$SERVER_NAME Git", or "Untitled Git" if this variable is not set (e.g. if running gitweb as standalone script).
Can be set using the GITWEB_SITENAME at build time. Unset by default.
Default value of ordering of projects on projects list page, which means the ordering used if you don't explicitly sort projects list (if there is no "o" CGI query parameter in the URL). Valid values are "none" (unsorted), "project" (projects are by project name, i.e. path to repository relative to $projectroot), "descr" (project description), "owner", and "age" (by date of most current commit).
Default value is "project". Unknown value means unsorted.
These configuration variables control internal gitweb behavior.
Rename detection options for git-diff and git-diff-tree. The default is ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or set it to () i.e. empty list if you don't want to have renames detection.
Note that rename and especially copy detection can be quite CPU-intensive. Note also that non Git tools can have problems with patches generated with options mentioned above, especially when they involve file copies ('-C') or criss-cross renames ('-B').
Most of features are configured via %feature hash; however some of extra gitweb features can be turned on and configured using variables described below. This list beside configuration variables that control how gitweb looks does contain variables configuring administrative side of gitweb (e.g. cross-site scripting prevention; admittedly this as side effect affects how "summary" pages look like, or load limiting).
List of Git base URLs. These URLs are used to generate URLs describing from where to fetch a project, which are shown on project summary page. The full fetch URL is "$git_base_url/$project", for each element of this list. You can set up multiple base URLs (for example one for git:// protocol, and one for http:// protocol).
Note that per repository configuration can be set in $GIT_DIR/cloneurl file, or as values of multi-value gitweb.url configuration variable in project config. Per-repository configuration takes precedence over value composed from @git_base_url_list elements and project name.
You can setup one single value (single entry/item in this list) at build time by setting the GITWEB_BASE_URL build-time configuration variable. By default it is set to (), i.e. an empty list. This means that gitweb would not try to create project URL (to fetch) from project name.
Used to set the maximum load that we will still respond to gitweb queries. If the server load exceeds this value then gitweb will return "503 Service Unavailable" error. The server load is taken to be 0 if gitweb cannot determine its value. Currently it works only on Linux, where it uses /proc/loadavg; the load there is the number of active tasks on the system -- processes that are actually running -- averaged over the last minute.
Set $maxload to undefined value (undef) to turn this feature off. The default value is 300.
If this is set to code reference, it will be run once for each request. You can set parts of configuration that change per session this way. For example, one might use the following code in a gitweb configuration file
our $per_request_config = sub {
$ENV{GL_USER} = $cgi->remote_user || "gitweb";
};If $per_request_config is not a code reference, it is interpreted as boolean value. If it is true gitweb will process config files once per request, and if it is false gitweb will process config files only once, each time it is executed. True by default (set to 1).
NOTE: $my_url, $my_uri, and $base_url are overwritten with their default values before every request, so if you want to change them, be sure to set this variable to true or a code reference effecting the desired changes.
This variable matters only when using persistent web environments that serve multiple requests using single gitweb instance, like mod_perl, FastCGI or Plackup.
Usually you should not need to change (adjust) any of configuration variables described below; they should be automatically set by gitweb to correct value.
Gitweb version, set automatically when creating gitweb.cgi from gitweb.perl. You might want to modify it if you are running modified gitweb, for example
our $version .= " with caching";
if you run modified version of gitweb with caching support. This variable is purely informational, used e.g. in the "generator" meta header in HTML header.
Many gitweb features can be enabled (or disabled) and configured using the %feature hash. Names of gitweb features are keys of this hash.
Each %feature hash element is a hash reference and has the following structure:
"<feature-name>" => {
"sub" => <feature-sub-(subroutine)>,
"override" => <allow-override-(boolean)>,
"default" => [ <options>... ]
},Some features cannot be overridden per project. For those features the structure of appropriate %feature hash element has a simpler form:
"<feature-name>" => {
"override" => 0,
"default" => [ <options>... ]
},As one can see it lacks the 'sub' element.
The meaning of each part of feature configuration is described below:
List (array reference) of feature parameters (if there are any), used also to toggle (enable or disable) given feature.
Note that it is currently always an array reference, even if feature doesn't accept any configuration parameters, and 'default' is used only to turn it on or off. In such case you turn feature on by setting this element to [1], and torn it off by setting it to [0]. See also the passage about the "blame" feature in the "Examples" section.
To disable features that accept parameters (are configurable), you need to set this element to empty list i.e. [].
If this field has a true value then the given feature is overridable, which means that it can be configured (or enabled/disabled) on a per-repository basis.
Usually given "<feature>" is configurable via the gitweb.<feature> config variable in the per-repository Git configuration file.
Note that no feature is overridable by default.
Internal detail of implementation. What is important is that if this field is not present then per-repository override for given feature is not supported.
You wouldn't need to ever change it in gitweb config file.
The gitweb features that are configurable via %feature hash are listed below. This should be a complete list, but ultimately the authoritative and complete list is in gitweb.cgi source code, with features described in the comments.
Enable the "blame" and "blame_incremental" blob views, showing for each line the last commit that modified it; see the section called “git-blame(1)”. This can be very CPU-intensive and is therefore disabled by default.
This feature can be configured on a per-repository basis via repository's gitweb.blame configuration variable (boolean).
Enable and configure the "snapshot" action, which allows user to download a compressed archive of any tree or commit, as produced by the section called “git-archive(1)” and possibly additionally compressed. This can potentially generate high traffic if you have large project.
The value of 'default' is a list of names of snapshot formats, defined in %known_snapshot_formats hash, that you wish to offer. Supported formats include "tgz", "tbz2", "txz" (gzip/bzip2/xz compressed tar archive) and "zip"; please consult gitweb sources for a definitive list. By default only "tgz" is offered.
This feature can be configured on a per-repository basis via repository's gitweb.snapshot configuration variable, which contains a comma separated list of formats or "none" to disable snapshots. Unknown values are ignored.
Enable grep search, which lists the files in currently selected tree (directory) containing the given string; see the section called “git-grep(1)”. This can be potentially CPU-intensive, of course. Enabled by default.
This feature can be configured on a per-repository basis via repository's gitweb.grep configuration variable (boolean).
Enable the so called pickaxe search, which will list the commits that introduced or removed a given string in a file. This can be practical and quite faster alternative to "blame" action, but it is still potentially CPU-intensive. Enabled by default.
The pickaxe search is described in the section called “git-log(1)” (the description of -S<string> option, which refers to pickaxe entry in the section called “gitdiffcore(7)” for more details).
This feature can be configured on a per-repository basis by setting repository's gitweb.pickaxe configuration variable (boolean).
Enable showing size of blobs (ordinary files) in a "tree" view, in a separate column, similar to what ls -l does; see description of -l option in the section called “git-ls-tree(1)” manpage. This costs a bit of I/O. Enabled by default.
This feature can be configured on a per-repository basis via repository's gitweb.showSizes configuration variable (boolean).
Enable and configure "patches" view, which displays list of commits in email (plain text) output format; see also the section called “git-format-patch(1)”. The value is the maximum number of patches in a patchset generated in "patches" view. Set the default field to a list containing single item of or to an empty list to disable patch view, or to a list containing a single negative number to remove any limit. Default value is 16.
This feature can be configured on a per-repository basis via repository's gitweb.patches configuration variable (integer).
Avatar support. When this feature is enabled, views such as "shortlog" or "commit" will display an avatar associated with the email of each committer and author.
Currently available providers are "gravatar" and "picon". Only one provider at a time can be selected (default is one element list). If an unknown provider is specified, the feature is disabled. Note that some providers might require extra Perl packages to be installed; see gitweb/INSTALL for more details.
This feature can be configured on a per-repository basis via repository's gitweb.avatar configuration variable.
See also %avatar_size with pixel sizes for icons and avatars ("default" is used for one-line like "log" and "shortlog", "double" is used for two-line like "commit", "commitdiff" or "tag"). If the default font sizes or lineheights are changed (e.g. via adding extra CSS stylesheet in @stylesheets), it may be appropriate to change these values.
Server-side syntax highlight support in "blob" view. It requires $highlight_bin program to be available (see the description of this variable in the "Configuration variables" section above), and therefore is disabled by default.
This feature can be configured on a per-repository basis via repository's gitweb.highlight configuration variable (boolean).
Enable displaying remote heads (remote-tracking branches) in the "heads" list. In most cases the list of remote-tracking branches is an unnecessary internal private detail, and this feature is therefore disabled by default. the section called “git-instaweb(1)”, which is usually used to browse local repositories, enables and uses this feature.
This feature can be configured on a per-repository basis via repository's gitweb.remote_heads configuration variable (boolean).
The remaining features cannot be overridden on a per project basis.
Enable text search, which will list the commits which match author, committer or commit text to a given string; see the description of --author, --committer and --grep options in the section called “git-log(1)” manpage. Enabled by default.
Project specific override is not supported.
If this feature is enabled, gitweb considers projects in
subdirectories of project root (basename) to be forks of existing
projects. For each project $projname.git, projects in the
$projname/ directory and its subdirectories will not be
shown in the main projects list. Instead, a '+' mark is shown
next to $projname, which links to a "forks" view that lists all
the forks (all projects in $projname/ subdirectory). Additionally
a "forks" view for a project is linked from project summary page.
If the project list is taken from a file ($projects_list points to a
file), forks are only recognized if they are listed after the main project
in that file.
Project specific override is not supported.
Insert custom links to the action bar of all project pages. This allows you to link to third-party scripts integrating into gitweb.
The "default" value consists of a list of triplets in the form ("<label>", "<link>", "<position>")` where "position" is the label after which to insert the link, "link" is a format string where %n expands to the project name, %f to the project path within the filesystem (i.e. "$projectroot/$project"), %h to the current hash ('h gitweb parameter) and %b` to the current hash base ('hb gitweb parameter); %%` expands to '%.
For example, at the time this page was written, the https://repo.or.cz Git hosting site set it to the following to enable graphical log (using the third party tool git-browser):
$feature{'actions'}{'default'} =
[ ('graphiclog', '/git-browser/by-commit.html?r=%n', 'summary')];This adds a link titled "graphiclog" after the "summary" link, leading to git-browser script, passing r=<project> as a query parameter.
Project specific override is not supported.
Enable displaying how much time and how many Git commands it took to generate and display each page in the page footer (at the bottom of page). For example the footer might contain: "This page took 6.53325 seconds and 13 Git commands to generate." Disabled by default.
Project specific override is not supported.
Enable and configure the ability to change a common time zone for dates in gitweb output via JavaScript. Dates in gitweb output include authordate and committerdate in "commit", "commitdiff" and "log" views, and taggerdate in "tag" view. Enabled by default.
The value is a list of three values: a default time zone (for if the client hasn't selected some other time zone and saved it in a cookie), a name of cookie where to store selected time zone, and a CSS class used to mark up dates for manipulation. If you want to turn this feature off, set "default" to empty list: [].
Typical gitweb config files will only change starting (default) time zone, and leave other elements at their default values:
$feature{'javascript-timezone'}{'default'}[0] = "utc";The example configuration presented here is guaranteed to be backwards and forward compatible.
Time zone values can be "local" (for local time zone that browser uses), "utc" (what gitweb uses when JavaScript or this feature is disabled), or numerical time zones in the form of "+/-HHMM", such as "+0200".
Project specific override is not supported.
List of additional directories under "refs" which are going to be used as branch refs. For example if you have a gerrit setup where all branches under refs/heads/ are official, push-after-review ones and branches under refs/sandbox/, refs/wip and refs/other are user ones where permissions are much wider, then you might want to set this variable as follows:
$feature{'extra-branch-refs'}{'default'} =
['sandbox', 'wip', 'other'];This feature can be configured on per-repository basis after setting $feature{extra-branch-refs}{override} to true, via repository's gitweb.extraBranchRefs configuration variable, which contains a space separated list of refs. An example:
[gitweb]
extraBranchRefs = sandbox wip otherThe gitweb.extraBranchRefs is actually a multi-valued configuration variable, so following example is also correct and the result is the same as of the snippet above:
[gitweb]
extraBranchRefs = sandbox
extraBranchRefs = wip otherIt is an error to specify a ref that does not pass "git check-ref-format" scrutiny. Duplicated values are filtered.
To enable blame, pickaxe search, and snapshot support (allowing "tar.gz" and "zip" snapshots), while allowing individual projects to turn them off, put the following in your GITWEB_CONFIG file:
$feature{'blame'}{'default'} = [1];
$feature{'blame'}{'override'} = 1;
$feature{'pickaxe'}{'default'} = [1];
$feature{'pickaxe'}{'override'} = 1;
$feature{'snapshot'}{'default'} = ['zip', 'tgz'];
$feature{'snapshot'}{'override'} = 1;If you allow overriding for the snapshot feature, you can specify which snapshot formats are globally disabled. You can also add any command-line options you want (such as setting the compression level). For instance, you can disable Zip compressed snapshots and set gzip(1) to run at level 6 by adding the following lines to your gitweb configuration file:
$known_snapshot_formats{'zip'}{'disabled'} = 1;
$known_snapshot_formats{'tgz'}{'compressor'} = ['gzip','-6'];Debugging would be easier if the fallback configuration file (/etc/gitweb.conf) and environment variable to override its location (GITWEB_CONFIG_SYSTEM) had names reflecting their "fallback" role. The current names are kept to avoid breaking working setups.
The location of per-instance and system-wide configuration files can be overridden using the following environment variables:
the section called “gitweb(1)”, the section called “git-instaweb(1)”
gitweb/README, gitweb/INSTALL
Part of the the section called “git(1)” suite
This document attempts to write down and motivate some of the workflow elements used for git.git itself. Many ideas apply in general, though the full workflow is rarely required for smaller projects with fewer people involved.
We formulate a set of rules for quick reference, while the prose tries to motivate each of them. Do not always take them literally; you should value good reasons for your actions higher than manpages such as this one.
As a general rule, you should try to split your changes into small logical steps, and commit each of them. They should be consistent, working independently of any later commits, pass the test suite, etc. This makes the review process much easier, and the history much more useful for later inspection and analysis, for example with the section called “git-blame(1)” and the section called “git-bisect(1)”.
To achieve this, try to split your work into small steps from the very beginning. It is always easier to squash a few commits together than to split one big commit into several. Don't be afraid of making too small or imperfect steps along the way. You can always go back later and edit the commits with git rebase --interactive before you publish them. You can use git stash push --keep-index to run the test suite independent of other uncommitted changes; see the EXAMPLES section of the section called “git-stash(1)”.
There are two main tools that can be used to include changes from one branch on another: the section called “git-merge(1)” and the section called “git-cherry-pick(1)”.
Merges have many advantages, so we try to solve as many problems as possible with merges alone. Cherry-picking is still occasionally useful; see "Merging upwards" below for an example.
Most importantly, merging works at the branch level, while cherry-picking works at the commit level. This means that a merge can carry over the changes from 1, 10, or 1000 commits with equal ease, which in turn means the workflow scales much better to a large number of contributors (and contributions). Merges are also easier to understand because a merge commit is a "promise" that all changes from all its parents are now included.
There is a tradeoff of course: merges require a more careful branch management. The following subsections discuss the important points.
As a given feature goes from experimental to stable, it also "graduates" between the corresponding branches of the software. git.git uses the following integration branches:
There is a fourth official branch that is used slightly differently:
Each of the four branches is usually a direct descendant of the one above it.
Conceptually, the feature enters at an unstable branch (usually next or seen), and "graduates" to master for the next release once it is considered stable enough.
The "downwards graduation" discussed above cannot be done by actually merging downwards, however, since that would merge all changes on the unstable branch into the stable one. Hence the following:
Example G.1. Merge upwards
Always commit your fixes to the oldest supported branch that requires them. Then (periodically) merge the integration branches upwards into each other.
This gives a very controlled flow of fixes. If you notice that you have applied a fix to e.g. master that is also required in maint, you will need to cherry-pick it (using the section called “git-cherry-pick(1)”) downwards. This will happen a few times and is nothing to worry about unless you do it very frequently.
Any nontrivial feature will require several patches to implement, and may get extra bugfixes or improvements during its lifetime.
Committing everything directly on the integration branches leads to many problems: Bad commits cannot be undone, so they must be reverted one by one, which creates confusing histories and further error potential when you forget to revert part of a group of changes. Working in parallel mixes up the changes, creating further confusion.
Use of "topic branches" solves these problems. The name is pretty self explanatory, with a caveat that comes from the "merge upwards" rule above:
Example G.2. Topic branches
Make a side branch for every topic (feature, bugfix, …). Fork it off at the oldest integration branch that you will eventually want to merge it into.
Many things can then be done very naturally:
Note that the last point clashes with the other two: a topic that has been merged elsewhere should not be rebased. See the section on RECOVERING FROM UPSTREAM REBASE in the section called “git-rebase(1)”.
We should point out that "habitually" (regularly for no real reason) merging an integration branch into your topics -- and by extension, merging anything upstream into anything downstream on a regular basis -- is frowned upon:
Example G.3. Merge to downstream only at well-defined points
Do not merge to downstream except with a good reason: upstream API changes affect your branch; your branch no longer merges to upstream cleanly; etc.
Otherwise, the topic that was merged to suddenly contains more than a single (well-separated) change. The many resulting small merges will greatly clutter up history. Anyone who later investigates the history of a file will have to find out whether that merge affected the topic in development. An upstream might even inadvertently be merged into a "more stable" branch. And so on.
If you followed the last paragraph, you will now have many small topic branches, and occasionally wonder how they interact. Perhaps the result of merging them does not even work? But on the other hand, we want to avoid merging them anywhere "stable" because such merges cannot easily be undone.
The solution, of course, is to make a merge that we can undo: merge into a throw-away branch.
Example G.4. Throw-away integration branches
To test the interaction of several topics, merge them into a throw-away branch. You must never base any work on such a branch!
If you make it (very) clear that this branch is going to be deleted right after the testing, you can even publish this branch, for example to give the testers a chance to work with it, or other developers a chance to see if their in-progress work will be compatible. git.git has such an official throw-away integration branch called seen.
Assuming you are using the merge approach discussed above, when you are releasing your project you will need to do some additional branch management work.
A feature release is created from the master branch, since master tracks the commits that should go into the next feature release.
The master branch is supposed to be a superset of maint. If this condition does not hold, then maint contains some commits that are not included on master. The fixes represented by those commits will therefore not be included in your feature release.
To verify that master is indeed a superset of maint, use git log:
This command should not list any commits. Otherwise, check out master and merge maint into it.
Now you can proceed with the creation of the feature release. Apply a tag to the tip of master indicating the release version:
You need to push the new tag to a public Git server (see "DISTRIBUTED WORKFLOWS" below). This makes the tag available to others tracking your project. The push could also trigger a post-update hook to perform release-related items such as building release tarballs and preformatted documentation pages.
Similarly, for a maintenance release, maint is tracking the commits to be released. Therefore, in the steps above simply tag and push maint rather than master.
After a feature release, you need to manage your maintenance branches.
First, if you wish to continue to release maintenance fixes for the feature release made before the recent one, then you must create another branch to track commits for that previous release.
To do this, the current maintenance branch is copied to another branch named with the previous release version number (e.g. maint-X.Y.(Z-1) where X.Y.Z is the current release).
The maint branch should now be fast-forwarded to the newly released code so that maintenance fixes can be tracked for the current release:
If the merge fails because it is not a fast-forward, then it is possible some fixes on maint were missed in the feature release. This will not happen if the content of the branches was verified as described in the previous section.
After a feature release, the integration branch next may optionally be rewound and rebuilt from the tip of master using the surviving topics on next:
Example G.9. Rewind and rebuild next
The advantage of doing this is that the history of next will be clean. For example, some topics merged into next may have initially looked promising, but were later found to be undesirable or premature. In such a case, the topic is reverted out of next but the fact remains in the history that it was once merged and reverted. By recreating next, you give another incarnation of such topics a clean slate to retry, and a feature release is a good point in history to do so.
If you do this, then you should make a public announcement indicating that next was rewound and rebuilt.
The same rewind and rebuild process may be followed for seen. A public announcement is not necessary since seen is a throw-away branch, as described above.
After the last section, you should know how to manage topics. In general, you will not be the only person working on the project, so you will have to share your work.
Roughly speaking, there are two important workflows: merge and patch. The important difference is that the merge workflow can propagate full history, including merges, while patches cannot. Both workflows can be used in parallel: in git.git, only subsystem maintainers use the merge workflow, while everyone else sends patches.
Note that the maintainer(s) may impose restrictions, such as "Signed-off-by" requirements, that all commits/patches submitted for inclusion must adhere to. Consult your project's documentation for more information.
The merge workflow works by copying branches between upstream and downstream. Upstream can merge contributions into the official history; downstream base their work on the official history.
There are three main tools that can be used for this:
Note the last point. Do not use git pull unless you actually want to merge the remote branch.
Getting changes out is easy:
Example G.10. Push/pull: Publishing branches/topics
git push <remote> <branch> and tell everyone where they can fetch from.
You will still have to tell people by other means, such as mail. (Git provides the the section called “git-request-pull(1)” to send preformatted pull requests to upstream maintainers to simplify this task.)
If you just want to get the newest copies of the integration branches, staying up to date is easy too:
Example G.11. Push/pull: Staying up to date
Use git fetch <remote> or git remote update to stay up to date.
Then simply fork your topic branches from the stable remotes as explained earlier.
If you are a maintainer and would like to merge other people's topic branches to the integration branches, they will typically send a request to do so by mail. Such a request looks like
Please pull from
<URL> <branch>In that case, git pull can do the fetch and merge in one go, as follows.
Occasionally, the maintainer may get merge conflicts when they try to pull changes from downstream. In this case, they can ask downstream to do the merge and resolve the conflicts themselves (perhaps they will know better how to resolve them). It is one of the rare cases where downstream should merge from upstream.
If you are a contributor that sends changes upstream in the form of emails, you should use topic branches as usual (see above). Then use the section called “git-format-patch(1)” to generate the corresponding emails (highly recommended over manually formatting them because it makes the maintainer's life easier).
Example G.13. format-patch/am: Publishing branches/topics
See the the section called “git-format-patch(1)” and the section called “git-send-email(1)” manpages for further usage notes.
If the maintainer tells you that your patch no longer applies to the current upstream, you will have to rebase your topic (you cannot use a merge because you cannot format-patch merges):
You can then fix the conflicts during the rebase. Presumably you have not published your topic other than by mail, so rebasing it is not a problem.
If you receive such a patch series (as maintainer, or perhaps as a reader of the mailing list it was sent to), save the mails to files, create a new topic branch and use git am to import the commits:
One feature worth pointing out is the three-way merge, which can help if you get conflicts: git am -3 will use index information contained in patches to figure out the merge base. See the section called “git-am(1)” for other options.
the section called “gittutorial(7)”, the section called “git-push(1)”, the section called “git-pull(1)”, the section called “git-merge(1)”, the section called “git-rebase(1)”, the section called “git-format-patch(1)”, the section called “git-send-email(1)”, the section called “git-am(1)”
Part of the the section called “git(1)” suite
As a noun: A single point in the Git history; the entire history of a project is represented as a set of interrelated commits. The word "commit" is often used by Git in the same places other revision control systems use the words "revision" or "version". Also used as a short hand for commit object.
As a verb: The action of storing a new snapshot of the project's state in the Git history, by creating a new commit representing the current state of the index and advancing HEAD to point at the new commit.
Referring to a symbolic ref: the action of accessing the reference pointed at by a symbolic ref. Recursive dereferencing involves repeating the aforementioned process on the resulting ref until a non-symbolic reference is found.
Referring to a tag object: the action of accessing the object a tag points at. Tags are recursively dereferenced by repeating the operation on the result object until the result has either a specified object type (where applicable) or any non-"tag" object type. A synonym for "recursive dereference" in the context of tags is "peel".
Referring to a commit object: the action of accessing the commit's tree object. Commits cannot be dereferenced recursively.
Unless otherwise specified, "dereferencing" as it used in the context of Git commands or protocols is implicitly recursive.
Normally the HEAD stores the name of a branch, and commands that operate on the history HEAD represents operate on the history leading to the tip of the branch the HEAD points at. However, Git also allows you to check out an arbitrary commit that isn't necessarily the tip of any particular branch. The HEAD in such a state is called "detached".
Note that commands that operate on the history of the current branch (e.g. git commit to build a new history on top of it) still work while the HEAD is detached. They update the HEAD to point at the tip of the updated history without affecting any branch. Commands that update or inquire information about the current branch (e.g. git branch --set-upstream-to that sets what remote-tracking branch the current branch integrates with) obviously do not work, as there is no (real) current branch to ask about in this state.
Grafts enable two otherwise different lines of development to be joined together by recording fake ancestry information for commits. This way you can make Git pretend the set of parents a commit has is different from what was recorded when the commit was created. Configured via the .git/info/grafts file.
Note that the grafts mechanism is outdated and can lead to problems transferring objects between repositories; see the section called “git-replace(1)” for a more flexible and robust system to do the same thing.
As a verb: To bring the contents of another branch (possibly from an external repository) into the current branch. In the case where the merged-in branch is from a different repository, this is done by first fetching the remote branch and then merging the result into the current branch. This combination of fetch and merge operations is called a pull. Merging is performed by an automatic process that identifies changes made since the branches diverged, and then applies all those changes together. In cases where changes conflict, manual intervention may be required to complete the merge.
As a noun: unless it is a fast-forward, a successful merge results in the creation of a new commit representing the result of the merge, and having as parents the tips of the merged branches. This commit is referred to as a "merge commit", or sometimes just a "merge".
Pattern used to limit paths in Git commands.
Pathspecs are used on the command line of "git ls-files", "git ls-tree", "git add", "git grep", "git diff", "git checkout", and many other commands to limit the scope of operations to some subset of the tree or working tree. See the documentation of each command for whether paths are relative to the current directory or toplevel. The pathspec syntax is as follows:
For example, Documentation/*.jpg will match all .jpg files in the Documentation subtree, including Documentation/chapter_1/figure_1.jpg.
A pathspec that begins with a colon : has special meaning. In the short form, the leading colon : is followed by zero or more "magic signature" letters (which optionally is terminated by another colon :), and the remainder is the pattern to match against the path. The "magic signature" consists of ASCII symbols that are neither alphanumeric, glob, regex special characters nor colon. The optional colon that terminates the "magic signature" can be omitted if the pattern begins with a character that does not belong to "magic signature" symbol set and is not a colon.
In the long form, the leading colon : is followed by an open parenthesis (, a comma-separated list of zero or more "magic words", and a close parentheses ), and the remainder is the pattern to match against the path.
A pathspec with only a colon means "there is no pathspec". This form should not be combined with other pathspec.
Git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not match a / in the pathname. For example, "Documentation/*.html" matches "Documentation/git.html" but not "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".
Two consecutive asterisks ("**") in patterns matched against full pathname may have special meaning:
Other consecutive asterisks are considered invalid.
Glob magic is incompatible with literal magic.
After attr: comes a space separated list of "attribute requirements", all of which must be met in order for the path to be considered a match; this is in addition to the usual non-magic pathspec pattern matching. See the section called “gitattributes(5)”.
Each of the attribute requirements for the path takes one of these forms:
"!ATTR" requires that the attribute ATTR be unspecified.
Note that when matching against a tree object, attributes are still obtained from working tree, not from the given tree object.
A ref that has different semantics than normal refs. These refs can be read via normal Git commands, but cannot be written to by commands like the section called “git-update-ref(1)”.
The following pseudorefs are known to Git:
A name that points to an object name or another ref (the latter is called a symbolic ref). For convenience, a ref can sometimes be abbreviated when used as an argument to a Git command; see the section called “gitrevisions(7)” for details. Refs are stored in the repository.
The ref namespace is hierarchical. Ref names must either start with refs/ or be located in the root of the hierarchy. For the latter, their name must follow these rules:
The name ends with "_HEAD" or is equal to "HEAD".
There are some irregular refs in the root of the hierarchy that do not match these rules. The following list is exhaustive and shall not be extended in the future:
MERGE_AUTOSTASH
Different subhierarchies are used for different purposes. For example, the refs/heads/ hierarchy is used to represent local branches whereas the refs/tags/ hierarchy is used to represent local tags..
the section called “gittutorial(7)”, the section called “gittutorial-2(7)”, the section called “gitcvs-migration(7)”, the section called “giteveryday(7)”, The Git User's Manual
Part of the the section called “git(1)” suite