Chapter 2. Getting Started
In this chapter, youâll get started working with Git by setting your defaults and preferences, and learn the basics of creating a repository and adding initial content to it.
Basic Configuration
Before starting in with Git, youâll want to set a few basic parameters using git config
. This command reads and changes Git configuration at the repository, personal, or system level. Your personal Git configuration is in ~/.gitconfig; this is a plain-text file, which you can edit directly as well, if you like. Its format is called INI style (after a file extension commonly used for it, though not by Git), and is divided into sections, like so:
[user] name = Richard E. Silverman [color] ui = auto # overall default for color usage [mergetool "ediff"] trustExitCode = true
Comments are introduced with a hash sign (#
) as shown, as is common in Unix configuration files. The parameters have full names qualified by the section in which they appear using a dot; for example, the parameters mentioned in this example are:
-
user.name
-
color.ui
-
mergetool.ediff.trustExitCode
You use these names when reading or setting parameters with git config
, rather than editing the file yourself. To set a parameter with git config
:
$ git config --{local,global,system} parameter value
If you give this command when your current directory is inside a Git repository, it implies --local
, and it will change the configuration for that repository only, in the file .git/config. Otherwise, the default is --global
, which applies to your overall personal Git configuration in ~/.gitconfig. The --system
option changes the system-wide configuration on the machine youâre logged into, which applies to all users; its location may vary, but is usually /etc/gitconfig. This file is usually writable only by a system administrator, so youâd need to be root to run this command to make a change. Itâs not common to do that anyway; usually this file would be maintained separately, perhaps using a configuration management system such as Puppet or Chef.
Git reads these three configurations, each if available, in the order system, global, then local. Settings made in a later configuration override those from an earlier one so that, for example, you can set your normal email address with --global
but change it for commits made in a specific repository if you use a different address when corresponding about that work.
Parameters that take Boolean (yes/no) values can be given as yes/no
, true/false
, or on/off
.
See git-config(1) for more detail on the format of the configuration files, its many parameters (some mentioned in this text and some not), and other uses of git config
, such as querying the current setting of a parameter.
Personal Identification
Git will guess your name and email address from the environment, but those may vary from one computer to another and may not be what you want. To set them:
$ git config --global user.name "Richard E. Silverman" $ git config --global user.email res@oreilly.com
If you use the same ~/.gitconfig in multiple contexts, say at home and at work, then this may be inconvenient. Git will take your email address from the EMAIL
environment variable before resorting to a guess, so you can leave it out of your Git configuration and set EMAIL
appropriately in the different contexts, usually with your shell startup files, such as .bashrc, .profile, .cshrc, and so on. There are other environment variables for finer control as well, such as GIT_AUTHOR_NAME
and GIT_COMMITTER_EMAIL
; these refer to the fact that Git maintains a distinction between the author of a change and the person who committed it. See git-commit-tree(1) for details, as well as Defining Your Own Formats.
Text Editor
When you use git commit
, you supply some free-form text, which is included in the commit; this is the âcommit message.â You can give this on the command line with the -m
switch, but you can also use your favorite text editor to compose the message instead. If you omit the -m
switch, Git starts a text editor to let you write your message. The default editor varies by platform; on Unix, it is the ubiquitous vi. You can customize this with the environment variables GIT_EDITOR
, EDITOR
, or VISUAL
(the latter two are respected by many other Unix programs as well), or by setting core.editor
. For example (reflecting the authorâs predilections):
$ git config --global core.editor emacs
Git uses the first of these variables it finds in the order given.
Commit ID Abbreviation
When referring directly to an object identifier, it is usually not necessary to quote the entire 40-character hexadecimal SHA-1 value; any initial substring unique to the current context will do. You can tell Git to abbreviate commit IDs generally with:
$ git config --global log.abbrevCommit yes $ git config --global core.abbrev 8
This improves readability in various places, especially in log output such as:
$ git log --pretty=oneline
222433ee Update draft release notes to 1.7.10
2fa91bd3 Merge branch 'maint'
70eb1307 Documentation: do not assume that n -> 1 in â¦
...
where the commit messages would otherwise be pushed halfway off the screen to the right by the full identifiers. core.abbrev
is the length of the shortened identifiers in digits; the default is 7 in most cases. To see the full identifiers as a per-command exception, use --no-abbrev-commit
. Note that when youâre quoting commit IDs in a public or âfor the recordâ context, it may be best to use the full ID, to avoid any future ambiguities.
Pagination
Git will automatically pipe output from many commands such as git log
and git status
to less(1) for pagination; you can select a different program with the core.pager
variable (or the environment variable GIT_PAGER
), and disable pagination entirely by setting this to be simply cat
(or something equivalently transparent). You can control pagination on a per-command basis by setting a Boolean pager.
, e.g., command
pager.status
for git status
(this can also be the name of the pager program to use for this specific command). You may also want to read the git-config(1) section on core.pager
, which discusses specific things Git does with the LESS
environment variable to affect the behavior of less(1).
Color
Many Git commands, including diff
, log
, and branch
, can use color to help you interpret their output, but these options are mostly off by default. To enable the use of color generally, set:
$ git config --global color.ui auto
(ui
stands for âuser interface.â) This will turn on most color options when Git is talking to a terminal (tty/pty device). You can then turn off color for individual commands if you prefer; for example, to disable it for git branch
(but leave it on for other functions):
$ git config --global color.branch no
Gitâs use of color is very configurable, down to defining new color names, specifying terminal control sequences, and using color in custom log formats. See git-config(1) and git-log(1) for details.
Cryptographic Keys
Git can use GnuPG (âgpgâ) to cryptographically sign tags and commits in order to verify the authenticity of sensitive assertions such as, âThis tagged commit contains the version 3.0 source code.â See git tag for more on signing tags. By default, Git passes your name and email address to GnuPG to select the signing key. If the combination of your Git and GnuPG settings doesnât select the correct key, you can set it explicitly with:
$ git config --global user.signingkey 6B4FB2D0
You can use any key identifier GnuPG supports; 6B4FB2D0
happens to be an ID for the authorâs personal key. You can also use one of the email addresses bound to the key you want, if itâs unique among your keys.
Command Aliases
Most systems provide a way to abbreviate long commands with user-defined command aliases; for instance, using alias
in your Unix bash shell startup file ~/.bashrc. Git has its own internal alias system as well, which may be more convenient. This command:
$ git config --global alias.cp cherry-pick
defines git cp
as an alias for git cherry-pick
. An exclamation point means to pass the alias definition to the shell, letting you use more complex aliases; for example, this definition in ~/.gitconfig:
[alias] setup = ! "git init; git add .; git commit"
defines an alias git setup
, which sets up a new repository using the contents of the current directory.
More generally, whenever you type git
, if something
something
is not a built-in command or defined alias, Git searches its installation path (often /usr/lib/git-core) and then your own search path for a program named git
-something
. So, you can make your own Git command git foo
just by placing a program in an executable file named git-foo somewhere on your personal path (usually, the value of the PATH
environment variable).
Getting Help
You can get help with a Git command or feature using Git itself, for example:
$ git help commit
This displays the documentation for the command git commit
. On Unix systems, this documentation is available via the usual man page system as well; this is equivalent:
$ man git-commit
References
- git-init(1)
- git-commit-tree(1)
- git-config(1)
- git-log(1) [âPretty Formatsâ]
Creating a New, Empty Repository
The command:
$ git init directory
creates the argument directory if needed, and a directory named .git inside it holding a new, empty Git repository. Aside from the repository itself in .git, that directory will hold the working tree: copies of the files and directories under version control that you will edit. The .git directory holds the files and data structures that form the repository itself, including the database of all historical revisions of all project files. Unlike CVS and (until recently) Subversion, there is no control directory in each directory of the working tree (CVS and .svn); there is just the one .git directory at the top of the project tree.
The default with no argument is the current directory; that is, a simple git init
creates a new .git in the current directory.
git init
is a safe command. It will not remove any existing files in the target directory, the usual pattern being that you are about to add those files to the new repository. It will also not damage an existing repository, even though it gives a somewhat heart-stopping message about âreinitializingâ if you do it; all this actually does is make some administrative updates, such as picking up new templates for âhookâ scripts made available by the system administrator (see Git Hooks).
Selected Options
-
--bare
-
Creates a âbareâ repository; that is, one without an associated working tree. The internal repository files that would otherwise be inside .git are instead created in the target directory itself, and certain repository options are set differently, principally
core.bare = yes
. A bare repository usually serves as a point of coordination for a centralized workflow, in which several people push and pull from that repository rather than directly among themselves; no one works with the bare copy directly. -
--shared
Sets group ownership, file permissions, and options to support multiple Unix accounts pushing into a non-bare repository. The normal expectation is that if someone wants to send you an update to a project youâre both working on, she will ask you to pull from her repository, so that one way or another you are the only person who ever actually modifies your repository. The usual file permissions reflect this, allowing only you to modify the repository files. The
--shared
option arranges permissions to allow others in a common Unix group to push directly into your repository, as well as pull from it. There are several settings for this option, manipulating the details of group ownership, file permissions, interactions with peopleâs umask settings, and so on; see git-init(1) for details.This arrangement isnât much used, though; ordinarily you and your coworker would simply pull from one anotherâs repositories into your own, or push to a shared bare repository. Pushing into a nonbare repository is awkward, because it will fail if you try to push the branch that is currently checked out in the remote (since that could invalidate the remoteâs working tree and index at any moment). A bare repository doesnât have a working tree or index (since no one is using it directly), and so does not have this limitation.
The .git Directory
Though the repository is usually stored in a directory named .git at the top of the working tree, there are ways to locate it elsewhere: you can use git --git-dir
to refer explicitly to another loction, or set the environment variable directory
GIT_DIR
. For simplicity and to match the common case, we will generally just refer to .git when talking about the repository directory.
Importing an Existing Project
These commands create a new repository and add all content in the current directory to it:
$ git init $ git add . $ git commit -m 'Begin Project Foo!'
To illustrate:
$ cd hello $ ls -l total 12 -rw-r----- 1 res res 50 Mar 4 19:54 README -rw-r----- 1 res res 127 Mar 4 19:53 hello.c -rw-r----- 1 res res 27 Mar 4 19:53 hello.h $ git init Initialized empty Git repository in /u/res/hello/.git/ $ git add . $ git commit -m 'Begin Project Foo!' [master (root-commit) cb9c236f] Begin Project Foo! 3 files changed, 13 insertions(+) create mode 100644 README create mode 100644 hello.c create mode 100644 hello.h
This creates a new Git repository .git in the current directory, and adds the contents of the entire directory tree rooted there to the repository as the initial commit on a new branch named master:
$ git branch * master $ git log --stat commit cb9c236f Author: Richard E. Silverman <res@oreilly.com> Date: Sun Mar 4 19:57:45 2012 -0500 Begin Project Foo! README | 3 +++ hello.c | 7 +++++++ hello.h | 3 +++ 3 files changed, 13 insertions(+)
In more detail: git add .
adds the current directory to the (initially empty) index; this includes files as well as directories and their contents, and so on, recursively. git commit
then creates a new tree object capturing the current state of the index, as well as a commit object with your comment text, personal identification, the current time, and so on, pointing to that tree. It records these in the object database, and then finally sets the master branch to the new commit; that is, makes the ref refs/heads/master
point to the new commit ID:
$ git log --pretty=oneline cb9c236f Begin Project Foo! $ git show-ref master cb9c236f refs/heads/master
git log
shows the ID of the most recent (and right now only) commit, and git show-ref master
shows the commit ID currently referred to by the branch master; you can see that they are the same.
Ignoring Files
While youâre working on a project, you may have files in your working directory that you want Git to simply ignore. If itâs a small project in an interpreted language, this may not happen so much, but itâs definitely an issue for projects that produce compiled code of any sort, or use tools like autoconf, or generate documentation automatically in various formats. Such files include:
- object code
- *.o, *.so, *.a, *.dll, *.exe
- bytecode
- *.jar (Java), *.elc (Emacs Lisp), *.pyc (Python)
- toolchain artifacts
- config.log, config.status, aclocal.m4, Makefile.in, config.h
Generally speaking, anything that is automatically generated you probably donât want tracked by Git, and you donât want Git constantly including them in listings or complaining about them either. Git looks at three different kinds of files to determine what to ignore, in order:
-
Files named .gitignore in your working tree. This is just another file to Git as far as content is concernedâit will list it as âuntrackedâ if itâs present but not in the repositoryâand so you normally add it to the repository content; thus, if this is shared work, you should only put things there that make sense for other people to ignore as well. You can actually put
.gitignore
in a .gitignore file, and cause it to ignore itself. All .gitignore files in the current and containing directories in the repository are read, with rules in files closer to the current directory overriding those in files farther away. - The per-repository file .git/info/exclude. This is part of your repository configuration, but not part of the repository content, so unlike a tracked .gitignore file, it is not automatically foisted upon people who clone your project. This is a good place to put things you find convenient to ignore for this project, but about which others might disagree (or if you simply decide not to use .gitignore files as a matter of policy, to avoid confusion).
-
A file named by the configuration variable
core.excludesfile
, if you set it. You might do this:
$ git config --global core.excludesfile ~/.gitignore
and keep a set of ignore patterns there that you want Git to always observe. Thatâs assuming your home directory is not itself inside a Git repository, of course, in which case you might want to name the file something else (and ask yourself if you donât perhaps like Git just a bit too much).
Syntax of âIgnore Patternsâ
See gitignore(5) for precise details; generally speaking, an ignore file uses shell âglobâ patterns and comments in the following fashion. Note the use of the exclamation point to introduce a negated pattern, overriding subcases of an earlier pattern. Git reads all patterns in a file to determine the disposition of a given path, rather than stopping at the first match, and the last matching line is the one that applies:
# Ignore this specific file in a subdirectory. conf/config.h # Ignore this specific file in the current directory. # (not â./â) /super-cool-program ## Patterns without slashes apply everywhere in this ## directory and below. # Ignore individual objects and object archives # (*.o and *.a). *.[oa] # Ignore shared objects... *.so # ... but don't ignore this file, or my boyfriend # will complain. !my.so # Ignore any directories named âtemp,â but still # notice regular files and symbolic links with # that name. temp/
In .git/info/exclude or your core.excludesfile, the âcurrent directoryâ indicated earlier is the top of the working tree.
Note that all this applies only to untracked files; you cannot tell Git to ignore changes to a tracked file this way. The command git update-index --assume-unchanged
is useful for that.
Note
Shell âglobsâ are simple patterns, not as powerful as regular expressions; Git uses them to indicate sets of files and refs. There are many slightly different versions of the glob syntax, as it has been around for a long time; the one used in Git is documented in the fnmatch(3) and glob(3) man pages. Simply put: *
matches a sequence of characters not containing /
; ?
matches a single character (again not /
); and [abc]
matches one character, which must be either a
, b
, or c
.
Get Git Pocket Guide now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.