It will be useful to have a git repository to experiment with as you
read this manual.
-The best way to get one is by using the gitlink:git-clone[1] command to
+The best way to get one is by using the linkgit:git-clone[1] command to
download a copy of an existing repository. If you don't already have a
project in mind, here are some interesting examples:
The initial clone may be time-consuming for a large project, but you
will only need to clone once.
-The clone command creates a new directory named after the project
-("git" or "linux-2.6" in the examples above). After you cd into this
+The clone command creates a new directory named after the project ("git"
+or "linux-2.6" in the examples above). After you cd into this
directory, you will see that it contains a copy of the project files,
-together with a special top-level directory named ".git", which
-contains all the information about the history of the project.
+called the <<def_working_tree,working tree>>, together with a special
+top-level directory named ".git", which contains all the information
+about the history of the project.
[[how-to-check-out]]
How to check out a different version of a project
interrelated snapshots of the project's contents. In git each such
version is called a <<def_commit,commit>>.
-A single git repository may contain multiple branches. It keeps track
-of them by keeping a list of <<def_head,heads>> which reference the
-latest commit on each branch; the gitlink:git-branch[1] command shows
+Those snapshots aren't necessarily all arranged in a single line from
+oldest to newest; instead, work may simultaneously proceed along
+parallel lines of development, called <<def_branch,branches>>, which may
+merge and diverge.
+
+A single git repository can track development on multiple branches. It
+does this by keeping a list of <<def_head,heads>> which reference the
+latest commit on each branch; the linkgit:git-branch[1] command shows
you the list of branch heads:
------------------------------------------------
Most projects also use <<def_tag,tags>>. Tags, like heads, are
references into the project's history, and can be listed using the
-gitlink:git-tag[1] command:
+linkgit:git-tag[1] command:
------------------------------------------------
$ git tag -l
while heads are expected to advance as development progresses.
Create a new branch head pointing to one of these versions and check it
-out using gitlink:git-checkout[1]:
+out using linkgit:git-checkout[1]:
------------------------------------------------
$ git checkout -b new v2.6.13
------------------------------------------------
The working directory then reflects the contents that the project had
-when it was tagged v2.6.13, and gitlink:git-branch[1] shows two
+when it was tagged v2.6.13, and linkgit:git-branch[1] shows two
branches, with an asterisk marking the currently checked-out branch:
------------------------------------------------
------------------------------
Every change in the history of a project is represented by a commit.
-The gitlink:git-show[1] command shows the most recent commit on the
+The linkgit:git-show[1] command shows the most recent commit on the
current branch:
------------------------------------------------
contents of the commit, you are guaranteed that the commit can never change
without its name also changing.
-In fact, in <<git-internals>> we shall see that everything stored in git
+In fact, in <<git-concepts>> we shall see that everything stored in git
history, including file data and directory contents, is stored in an object
with a name that is a hash of its contents.
each parent representing the most recent commit on one of the lines
of development leading to that point.
-The best way to see how this works is using the gitlink:gitk[1]
+The best way to see how this works is using the linkgit:gitk[1]
command; running gitk now on a git repository and looking for merge
commits will help understand how the git organizes history.
of the HEAD in the repository that you cloned from. That repository
may also have had other branches, though, and your local repository
keeps branches which track each of those remote branches, which you
-can view using the "-r" option to gitlink:git-branch[1]:
+can view using the "-r" option to linkgit:git-branch[1]:
------------------------------------------------
$ git branch -r
The full name is occasionally useful if, for example, there ever
exists a tag and a branch with the same name.
+(Newly created refs are actually stored in the .git/refs directory,
+under the path given by their name. However, for efficiency reasons
+they may also be packed together in a single file; see
+linkgit:git-pack-refs[1]).
+
As another useful shortcut, the "HEAD" of a repository can be referred
to just using the name of that repository. So, for example, "origin"
is usually a shortcut for the HEAD branch in the repository "origin".
For the complete list of paths which git checks for references, and
the order it uses to decide which to choose when there are multiple
references with the same shorthand name, see the "SPECIFYING
-REVISIONS" section of gitlink:git-rev-parse[1].
+REVISIONS" section of linkgit:git-rev-parse[1].
[[Updating-a-repository-with-git-fetch]]
Updating a repository with git fetch
-----------------------------------------
You can also track branches from repositories other than the one you
-cloned from, using gitlink:git-remote[1]:
+cloned from, using linkgit:git-remote[1]:
-------------------------------------------------
$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
This is what causes git to track the remote's branches; you may modify
or delete these configuration options by editing .git/config with a
text editor. (See the "CONFIGURATION FILE" section of
-gitlink:git-config[1] for details.)
+linkgit:git-config[1] for details.)
[[exploring-git-history]]
Exploring git history
"master" crashes. Sometimes the best way to find the cause of such a
regression is to perform a brute-force search through the project's
history to find the particular commit that caused the problem. The
-gitlink:git-bisect[1] command can help you do this:
+linkgit:git-bisect[1] command can help you do this:
-------------------------------------------------
$ git bisect start
If you run "git branch" at this point, you'll see that git has
temporarily moved you to a new branch named "bisect". This branch
points to a commit (with commit id 65934...) that is reachable from
-v2.6.19 but not from v2.6.18. Compile and test it, and see whether
+"master" but not from v2.6.18. Compile and test it, and see whether
it crashes. Assume it does crash. Then:
-------------------------------------------------
After about 13 tests (in this case), it will output the commit id of
the guilty commit. You can then examine the commit with
-gitlink:git-show[1], find out who wrote it, and mail them your bug
+linkgit:git-show[1], find out who wrote it, and mail them your bug
report with the commit id. Finally, run
-------------------------------------------------
- HEAD: refers to the head of the current branch
There are many more; see the "SPECIFYING REVISIONS" section of the
-gitlink:git-rev-parse[1] man page for the complete list of ways to
+linkgit:git-rev-parse[1] man page for the complete list of ways to
name revisions. Some examples:
-------------------------------------------------
which refers to the other branch that we're merging in to the current
branch.
-The gitlink:git-rev-parse[1] command is a low-level command that is
+The linkgit:git-rev-parse[1] command is a low-level command that is
occasionally useful for translating some name for a commit to the object
name for that commit:
This creates a "lightweight" tag. If you would also like to include a
comment with the tag, and possibly sign it cryptographically, then you
-should create a tag object instead; see the gitlink:git-tag[1] man page
+should create a tag object instead; see the linkgit:git-tag[1] man page
for details.
[[browsing-revisions]]
Browsing revisions
------------------
-The gitlink:git-log[1] command can show lists of commits. On its
+The linkgit:git-log[1] command can show lists of commits. On its
own, it shows all commits reachable from the parent commit; but you
can also make more specific requests:
$ git log -p
-------------------------------------------------
-See the "--pretty" option in the gitlink:git-log[1] man page for more
+See the "--pretty" option in the linkgit:git-log[1] man page for more
display options.
Note that git log starts with the most recent commit and works
----------------
You can generate diffs between any two versions using
-gitlink:git-diff[1]:
+linkgit:git-diff[1]:
-------------------------------------------------
$ git diff master..test
-------------------------------------------------
-Sometimes what you want instead is a set of patches:
+That will produce the diff between the tips of the two branches. If
+you'd prefer to find the diff from their common ancestor to test, you
+can use three dots instead of two:
+
+-------------------------------------------------
+$ git diff master...test
+-------------------------------------------------
+
+Sometimes what you want instead is a set of patches; for this you can
+use linkgit:git-format-patch[1]:
-------------------------------------------------
$ git format-patch master..test
-------------------------------------------------
will generate a file with a patch for each commit reachable from test
-but not from master. Note that if master also has commits which are
-not reachable from test, then the combined result of these patches
-will not be the same as the diff produced by the git-diff example.
+but not from master.
[[viewing-old-file-versions]]
Viewing old file versions
-------------------------------------------------
Alternatively, you may often see this sort of thing done with the
-lower-level command gitlink:git-rev-list[1], which just lists the SHA1's
+lower-level command linkgit:git-rev-list[1], which just lists the SHA1's
of all the given commits:
-------------------------------------------------
$ gitk e05db0fd..
-------------------------------------------------
-Or you can use gitlink:git-name-rev[1], which will give the commit a
+Or you can use linkgit:git-name-rev[1], which will give the commit a
name based on any tag it finds pointing to one of the commit's
descendants:
e05db0fd tags/v1.5.0-rc1^0~23
-------------------------------------------------
-The gitlink:git-describe[1] command does the opposite, naming the
+The linkgit:git-describe[1] command does the opposite, naming the
revision using a tag on which the given commit is based:
-------------------------------------------------
given commit.
If you just want to verify whether a given tagged version contains a
-given commit, you could use gitlink:git-merge-base[1]:
+given commit, you could use linkgit:git-merge-base[1]:
-------------------------------------------------
$ git merge-base e05db0fd v1.5.0-rc1
will produce empty output if and only if v1.5.0-rc1 includes e05db0fd,
because it outputs only commits that are not reachable from v1.5.0-rc1.
-As yet another alternative, the gitlink:git-show-branch[1] command lists
+As yet another alternative, the linkgit:git-show-branch[1] command lists
the commits reachable from its arguments with a display on the left-hand
side that indicates which arguments that commit is reachable from. So,
you can run something like
head named "master" but not from any other head in your repository.
We can list all the heads in this repository with
-gitlink:git-show-ref[1]:
+linkgit:git-show-ref[1]:
-------------------------------------------------
$ git show-ref --heads
$ gitk $( git show-ref --heads ) --not $( git show-ref --tags )
-------------------------------------------------
-(See gitlink:git-rev-parse[1] for explanations of commit-selecting
+(See linkgit:git-rev-parse[1] for explanations of commit-selecting
syntax such as `--not`.)
[[making-a-release]]
Creating a changelog and tarball for a software release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The gitlink:git-archive[1] command can create a tar or zip archive from
+The linkgit:git-archive[1] command can create a tar or zip archive from
any version of a project; for example:
-------------------------------------------------
commit. You can find out with this:
-------------------------------------------------
-$ git log --raw --abbrev=40 --pretty=oneline -- filename |
+$ git log --raw --abbrev=40 --pretty=oneline |
grep -B 1 `git hash-object filename`
-------------------------------------------------
Figuring out why this works is left as an exercise to the (advanced)
-student. The gitlink:git-log[1], gitlink:git-diff-tree[1], and
-gitlink:git-hash-object[1] man pages may prove helpful.
+student. The linkgit:git-log[1], linkgit:git-diff-tree[1], and
+linkgit:git-hash-object[1] man pages may prove helpful.
[[Developing-with-git]]
Developing with git
email = you@yourdomain.example.com
------------------------------------------------
-(See the "CONFIGURATION FILE" section of gitlink:git-config[1] for
+(See the "CONFIGURATION FILE" section of linkgit:git-config[1] for
details on the configuration file.)
$ git status # a brief per-file summary of the above.
-------------------------------------------------
-You can also use gitlink:git-gui[1] to create commits, view changes in
+You can also use linkgit:git-gui[1] to create commits, view changes in
the index and the working tree files, and individually select diff hunks
for inclusion in the index (by right-clicking on the diff hunk and
choosing "Stage Hunk For Commit").
*.[oa]
-------------------------------------------------
-See gitlink:gitignore[5] for a detailed explanation of the syntax. You can
+See linkgit:gitignore[5] for a detailed explanation of the syntax. You can
also place .gitignore files in other directories in your working tree, and they
will apply to those directories and their subdirectories. The `.gitignore`
files can be added to your repository like any other files (just run `git add
them in a file in your repository named .git/info/exclude, or in any file
specified by the `core.excludesfile` configuration variable. Some git
commands can also take exclude patterns directly on the command line.
-See gitlink:gitignore[5] for the details.
+See linkgit:gitignore[5] for the details.
[[how-to-merge]]
How to merge
------------
You can rejoin two diverging branches of development using
-gitlink:git-merge[1]:
+linkgit:git-merge[1]:
-------------------------------------------------
$ git merge branchname
information you need to help resolve the merge.
Files with conflicts are marked specially in the index, so until you
-resolve the problem and update the index, gitlink:git-commit[1] will
+resolve the problem and update the index, linkgit:git-commit[1] will
fail:
-------------------------------------------------
file.txt: needs merge
-------------------------------------------------
-Also, gitlink:git-status[1] will list those files as "unmerged", and the
+Also, linkgit:git-status[1] will list those files as "unmerged", and the
files with conflicts will have conflict markers added, like this:
-------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All of the changes that git was able to merge automatically are
-already added to the index file, so gitlink:git-diff[1] shows only
+already added to the index file, so linkgit:git-diff[1] shows only
the conflicts. It uses an unusual syntax:
-------------------------------------------------
Since the stage 2 and stage 3 versions have already been updated with
nonconflicting changes, the only remaining differences between them are
-the important ones; thus gitlink:git-diff[1] can use the information in
+the important ones; thus linkgit:git-diff[1] can use the information in
the index to show only those conflicts.
The diff above shows the differences between the working-tree version of
column is used for differences between the first parent and the working
directory copy, and the second for differences between the second parent
and the working directory copy. (See the "COMBINED DIFF FORMAT" section
-of gitlink:git-diff-files[1] for a details of the format.)
+of linkgit:git-diff-files[1] for a details of the format.)
After resolving the conflict in the obvious way (but before updating the
index), the diff will look like:
$ git diff --theirs file.txt # same as the above.
-------------------------------------------------
-The gitlink:git-log[1] and gitk[1] commands also provide special help
+The linkgit:git-log[1] and gitk[1] commands also provide special help
for merges:
-------------------------------------------------
These will display all commits which exist only on HEAD or on
MERGE_HEAD, and which touch an unmerged file.
-You may also use gitlink:git-mergetool[1], which lets you merge the
+You may also use linkgit:git-mergetool[1], which lets you merge the
unmerged files using external tools such as emacs or kdiff3.
Each time you resolve the conflicts in a file and update the index:
fundamentally different ways to fix the problem:
1. You can create a new commit that undoes whatever was done
- by the previous commit. This is the correct thing if your
+ by the old commit. This is the correct thing if your
mistake has already been made public.
2. You can go back and modify the old commit. You should
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creating a new commit that reverts an earlier change is very easy;
-just pass the gitlink:git-revert[1] command a reference to the bad
+just pass the linkgit:git-revert[1] command a reference to the bad
commit; for example, to revert the most recent commit:
-------------------------------------------------
conflicts manually, just as in the case of <<resolving-a-merge,
resolving a merge>>.
-[[fixing-a-mistake-by-editing-history]]
-Fixing a mistake by editing history
+[[fixing-a-mistake-by-rewriting-history]]
+Fixing a mistake by rewriting history
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the problematic commit is the most recent commit, and you have not
changes, giving you a chance to edit the old commit message first.
Again, you should never do this to a commit that may already have
-been merged into another branch; use gitlink:git-revert[1] instead in
+been merged into another branch; use linkgit:git-revert[1] instead in
that case.
-It is also possible to edit commits further back in the history, but
+It is also possible to replace commits further back in the history, but
this is an advanced topic to be left for
<<cleaning-up-history,another chapter>>.
In the process of undoing a previous bad change, you may find it
useful to check out an older version of a particular file using
-gitlink:git-checkout[1]. We've used git checkout before to switch
+linkgit:git-checkout[1]. We've used git checkout before to switch
branches, but it has quite different behavior if it is given a path
name: the command
If you just want to look at an old version of the file, without
modifying the working directory, you can do that with
-gitlink:git-show[1]:
+linkgit:git-show[1]:
-------------------------------------------------
$ git show HEAD^:path/to/file
While you are in the middle of working on something complicated, you
find an unrelated but obvious and trivial bug. You would like to fix it
-before continuing. You can use gitlink:git-stash[1] to save the current
+before continuing. You can use linkgit:git-stash[1] to save the current
state of your work, and after fixing the bug (or, optionally after doing
so on a different branch and then coming back), unstash the
work-in-progress changes.
-------------------------
On large repositories, git depends on compression to keep the history
-information from taking up to much space on disk or in memory.
+information from taking up too much space on disk or in memory.
This compression is not performed automatically. Therefore you
-should occasionally run gitlink:git-gc[1]:
+should occasionally run linkgit:git-gc[1]:
-------------------------------------------------
$ git gc
Checking the repository for corruption
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The gitlink:git-fsck[1] command runs a number of self-consistency checks
+The linkgit:git-fsck[1] command runs a number of self-consistency checks
on the repository, and reports on any problems. This may take some
time. The most common warning by far is about "dangling" objects:
Dangling objects are not a problem. At worst they may take up a little
extra disk space. They can sometimes provide a last-resort method for
recovering lost work--see <<dangling-objects>> for details. However, if
-you wish, you can remove them with gitlink:git-prune[1] or the --prune
-option to gitlink:git-gc[1]:
+you wish, you can remove them with linkgit:git-prune[1] or the `--prune`
+option to linkgit:git-gc[1]:
-------------------------------------------------
$ git gc --prune
git-gc when run without any options), it is not safe to prune while
other git operations are in progress in the same repository.
+If linkgit:git-fsck[1] complains about sha1 mismatches or missing
+objects, you may have a much more serious problem; your best option is
+probably restoring from backups. See
+<<recovering-from-repository-corruption>> for a detailed discussion.
+
[[recovering-lost-changes]]
Recovering lost changes
~~~~~~~~~~~~~~~~~~~~~~~
Reflogs
^^^^^^^
-Say you modify a branch with gitlink:git-reset[1] --hard, and then
+Say you modify a branch with `linkgit:git-reset[1] --hard`, and then
realize that the branch was the only reference you had to that point in
history.
$ git log master@{1}
-------------------------------------------------
-This lists the commits reachable from the previous version of the head.
-This syntax can be used to with any git command that accepts a commit,
-not just with git log. Some other examples:
+This lists the commits reachable from the previous version of the
+"master" branch head. This syntax can be used with any git command
+that accepts a commit, not just with git log. Some other examples:
-------------------------------------------------
$ git show master@{2} # See where the branch pointed 2,
you've checked out.
The reflogs are kept by default for 30 days, after which they may be
-pruned. See gitlink:git-reflog[1] and gitlink:git-gc[1] to learn
+pruned. See linkgit:git-reflog[1] and linkgit:git-gc[1] to learn
how to control this pruning, and see the "SPECIFYING REVISIONS"
-section of gitlink:git-rev-parse[1] for details.
+section of linkgit:git-rev-parse[1] for details.
Note that the reflog history is very different from normal git history.
While normal history is shared by every repository that works on the
into your own work.
We have already seen <<Updating-a-repository-with-git-fetch,how to
-keep remote tracking branches up to date>> with gitlink:git-fetch[1],
+keep remote tracking branches up to date>> with linkgit:git-fetch[1],
and how to merge two branches. So you can merge in changes from the
original repository's master branch with:
$ git merge origin/master
-------------------------------------------------
-However, the gitlink:git-pull[1] command provides a way to do this in
+However, the linkgit:git-pull[1] command provides a way to do this in
one step:
-------------------------------------------------
More generally, a branch that is created from a remote branch will pull
by default from that branch. See the descriptions of the
branch.<name>.remote and branch.<name>.merge options in
-gitlink:git-config[1], and the discussion of the --track option in
-gitlink:git-checkout[1], to learn how to control these defaults.
+linkgit:git-config[1], and the discussion of the `--track` option in
+linkgit:git-checkout[1], to learn how to control these defaults.
In addition to saving you keystrokes, "git pull" also helps you by
producing a default commit message documenting the branch and
If you just have a few changes, the simplest way to submit them may
just be to send them as patches in email:
-First, use gitlink:git-format-patch[1]; for example:
+First, use linkgit:git-format-patch[1]; for example:
-------------------------------------------------
$ git format-patch origin
You can then import these into your mail client and send them by
hand. However, if you have a lot to send at once, you may prefer to
-use the gitlink:git-send-email[1] script to automate the process.
+use the linkgit:git-send-email[1] script to automate the process.
Consult the mailing list for your project first to determine how they
prefer such patches be handled.
Importing patches to a project
------------------------------
-Git also provides a tool called gitlink:git-am[1] (am stands for
+Git also provides a tool called linkgit:git-am[1] (am stands for
"apply mailbox"), for importing such an emailed series of patches.
Just save all of the patch-containing messages, in order, into a
single mailbox file, say "patches.mbox", then run
Another way to submit changes to a project is to tell the maintainer
of that project to pull the changes from your repository using
-gitlink:git-pull[1]. In the section "<<getting-updates-with-git-pull,
+linkgit:git-pull[1]. In the section "<<getting-updates-with-git-pull,
Getting updates with git pull>>" we described this as a way to get
updates from the "main" repository, but it works just as well in the
other direction.
$ git pull /path/to/other/repository
-------------------------------------------------
-or an ssh url:
+or an ssh URL:
-------------------------------------------------
$ git clone ssh://yourhost/~you/repository
This is the preferred method.
If someone else administers the server, they should tell you what
-directory to put the repository in, and what git:// url it will appear
+directory to put the repository in, and what git:// URL it will appear
at. You can then skip to the section
"<<pushing-changes-to-a-public-repository,Pushing changes to a public
repository>>", below.
-Otherwise, all you need to do is start gitlink:git-daemon[1]; it will
+Otherwise, all you need to do is start linkgit:git-daemon[1]; it will
listen on port 9418. By default, it will allow access to any directory
that looks like a git directory and contains the magic file
git-daemon-export-ok. Passing some directory paths as git-daemon
arguments will further restrict the exports to those paths.
You can also run git-daemon as an inetd service; see the
-gitlink:git-daemon[1] man page for details. (See especially the
+linkgit:git-daemon[1] man page for details. (See especially the
examples section.)
[[exporting-via-http]]
-------------------------------------------------
(For an explanation of the last two lines, see
-gitlink:git-update-server-info[1], and the documentation
+linkgit:git-update-server-info[1], and the documentation
link:hooks.html[Hooks used by git].)
-Advertise the url of proj.git. Anybody else should then be able to
-clone or pull from that url, for example with a command line like:
+Advertise the URL of proj.git. Anybody else should then be able to
+clone or pull from that URL, for example with a command line like:
-------------------------------------------------
$ git clone http://yourserver.com/~you/proj.git
access, which you will need to update the public repository with the
latest changes created in your private repository.
-The simplest way to do this is using gitlink:git-push[1] and ssh; to
+The simplest way to do this is using linkgit:git-push[1] and ssh; to
update the remote branch named "master" with the latest state of your
branch named "master", run
$ git push ssh://yourserver.com/~you/proj.git master
-------------------------------------------------
-As with git-fetch, git-push will complain if this does not result in
-a <<fast-forwards,fast forward>>. Normally this is a sign of
-something wrong. However, if you are sure you know what you're
-doing, you may force git-push to perform the update anyway by
-proceeding the branch name by a plus sign:
-
--------------------------------------------------
-$ git push ssh://yourserver.com/~you/proj.git +master
--------------------------------------------------
+As with git-fetch, git-push will complain if this does not result in a
+<<fast-forwards,fast forward>>; see the following section for details on
+handling this case.
Note that the target of a "push" is normally a
<<def_bare_repository,bare>> repository. You can also push to a
-------------------------------------------------
See the explanations of the remote.<name>.url, branch.<name>.remote,
-and remote.<name>.push options in gitlink:git-config[1] for
+and remote.<name>.push options in linkgit:git-config[1] for
details.
+[[forcing-push]]
+What to do when a push fails
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a push would not result in a <<fast-forwards,fast forward>> of the
+remote branch, then it will fail with an error like:
+
+-------------------------------------------------
+error: remote 'refs/heads/master' is not an ancestor of
+ local 'refs/heads/master'.
+ Maybe you are not up-to-date and need to pull first?
+error: failed to push to 'ssh://yourserver.com/~you/proj.git'
+-------------------------------------------------
+
+This can happen, for example, if you:
+
+ - use `git reset --hard` to remove already-published commits, or
+ - use `git commit --amend` to replace already-published commits
+ (as in <<fixing-a-mistake-by-rewriting-history>>), or
+ - use `git rebase` to rebase any already-published commits (as
+ in <<using-git-rebase>>).
+
+You may force git-push to perform the update anyway by preceding the
+branch name with a plus sign:
+
+-------------------------------------------------
+$ git push ssh://yourserver.com/~you/proj.git +master
+-------------------------------------------------
+
+Normally whenever a branch head in a public repository is modified, it
+is modified to point to a descendant of the commit that it pointed to
+before. By forcing a push in this situation, you break that convention.
+(See <<problems-with-rewriting-history>>.)
+
+Nevertheless, this is a common practice for people that need a simple
+way to publish a work-in-progress patch series, and it is an acceptable
+compromise as long as you warn other developers that this is how you
+intend to manage the branch.
+
+It's also possible for a push to fail in this way when other people have
+the right to push to the same repository. In that case, the correct
+solution is to retry the push after first updating your work by either a
+pull or a fetch followed by a rebase; see the
+<<setting-up-a-shared-repository,next section>> and
+link:cvs-migration.html[git for CVS users] for more.
+
[[setting-up-a-shared-repository]]
Setting up a shared repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------------------------------
Linus's tree will be stored in the remote branch named origin/master,
-and can be updated using gitlink:git-fetch[1]; you can track other
-public trees using gitlink:git-remote[1] to set up a "remote" and
-gitlink:git-fetch[1] to keep them up-to-date; see
+and can be updated using linkgit:git-fetch[1]; you can track other
+public trees using linkgit:git-remote[1] to set up a "remote" and
+linkgit:git-fetch[1] to keep them up-to-date; see
<<repositories-and-branches>>.
Now create the branches in which you are going to work; these start out
at the current tip of origin/master branch, and should be set up (using
-the --track option to gitlink:git-branch[1]) to merge changes in from
+the --track option to linkgit:git-branch[1]) to merge changes in from
Linus by default.
-------------------------------------------------
$ git branch --track release origin/master
-------------------------------------------------
-These can be easily kept up to date using gitlink:git-pull[1]
+These can be easily kept up to date using linkgit:git-pull[1].
-------------------------------------------------
$ git checkout test && git pull
will become part of the permanent history when you ask Linus to pull
from the release branch.
-A few configuration variables (see gitlink:git-config[1]) can
+A few configuration variables (see linkgit:git-config[1]) can
make it easy to push both branches to your public tree. (See
<<setting-up-a-public-repository>>.)
-------------------------------------------------
Then you can push both the test and release trees using
-gitlink:git-push[1]:
+linkgit:git-push[1]:
-------------------------------------------------
$ git push mytree
$ git log linux..branchname | git-shortlog
-------------------------------------------------
-To see whether it has already been merged into the test or release branches
+To see whether it has already been merged into the test or release branches,
use:
-------------------------------------------------
$ git log release..branchname
-------------------------------------------------
-(If this branch has not yet been merged you will see some log entries.
+(If this branch has not yet been merged, you will see some log entries.
If it has been merged, then there will be no output.)
Once a patch completes the great cycle (moving from test to release,
then pulled by Linus, and finally coming back into your local
-"origin/master" branch) the branch for this change is no longer needed.
+"origin/master" branch), the branch for this change is no longer needed.
You detect this when the output from:
-------------------------------------------------
git checkout $1 && git pull . origin
;;
origin)
- before=$(cat .git/refs/remotes/origin/master)
+ before=$(git rev-parse refs/remotes/origin/master)
git fetch origin
- after=$(cat .git/refs/remotes/origin/master)
+ after=$(git rev-parse refs/remotes/origin/master)
if [ $before != $after ]
then
git log $before..$after | git shortlog
exit 1
}
-if [ ! -f .git/refs/heads/"$1" ]
-then
+git show-ref -q --verify -- refs/heads/"$1" || {
echo "Can't see branch <$1>" 1>&2
usage
-fi
+}
case "$2" in
test|release)
git log test..release
fi
-for branch in `ls .git/refs/heads`
+for branch in `git show-ref --heads | sed 's|^.*/||'`
do
if [ $branch = test -o $branch = release ]
then
However, if you prefer to keep the history in mywork a simple series of
commits without any merges, you may instead choose to use
-gitlink:git-rebase[1]:
+linkgit:git-rebase[1]:
-------------------------------------------------
$ git checkout mywork
and git will continue applying the rest of the patches.
-At any point you may use the --abort option to abort this process and
+At any point you may use the `--abort` option to abort this process and
return mywork to the state it had before you started the rebase:
-------------------------------------------------
$ git rebase --abort
-------------------------------------------------
-[[modifying-one-commit]]
-Modifying a single commit
+[[rewriting-one-commit]]
+Rewriting a single commit
-------------------------
-We saw in <<fixing-a-mistake-by-editing-history>> that you can replace the
+We saw in <<fixing-a-mistake-by-rewriting-history>> that you can replace the
most recent commit using
-------------------------------------------------
which will replace the old commit by a new commit incorporating your
changes, giving you a chance to edit the old commit message first.
-You can also use a combination of this and gitlink:git-rebase[1] to edit
-commits further back in your history. First, tag the problematic commit with
+You can also use a combination of this and linkgit:git-rebase[1] to
+replace a commit further back in your history and recreate the
+intervening changes on top of it. First, tag the problematic commit
+with
-------------------------------------------------
$ git tag bad mywork~5
Reordering or selecting from a patch series
-------------------------------------------
-Given one existing commit, the gitlink:git-cherry-pick[1] command
+Given one existing commit, the linkgit:git-cherry-pick[1] command
allows you to apply the change introduced by that commit and create a
new commit that records it. So, for example, if "mywork" points to a
series of patches on top of "origin", you might do something like:
$ gitk origin..mywork &
-------------------------------------------------
-And browse through the list of patches in the mywork branch using gitk,
+and browse through the list of patches in the mywork branch using gitk,
applying them (possibly in a different order) to mywork-new using
-cherry-pick, and possibly modifying them as you go using commit --amend.
-The gitlink:git-gui[1] command may also help as it allows you to
+cherry-pick, and possibly modifying them as you go using `commit --amend`.
+The linkgit:git-gui[1] command may also help as it allows you to
individually select diff hunks for inclusion in the index (by
right-clicking on the diff hunk and choosing "Stage Hunk for Commit").
-------------------------------------------------
Then modify, reorder, or eliminate patches as preferred before applying
-them again with gitlink:git-am[1].
+them again with linkgit:git-am[1].
[[patch-series-tools]]
Other tools
For true distributed development that supports proper merging,
published branches should never be rewritten.
+[[bisect-merges]]
+Why bisecting merge commits can be harder than bisecting linear history
+-----------------------------------------------------------------------
+
+The linkgit:git-bisect[1] command correctly handles history that
+includes merge commits. However, when the commit that it finds is a
+merge commit, the user may need to work harder than usual to figure out
+why that commit introduced a problem.
+
+Imagine this history:
+
+................................................
+ ---Z---o---X---...---o---A---C---D
+ \ /
+ o---o---Y---...---o---B
+................................................
+
+Suppose that on the upper line of development, the meaning of one
+of the functions that exists at Z is changed at commit X. The
+commits from Z leading to A change both the function's
+implementation and all calling sites that exist at Z, as well
+as new calling sites they add, to be consistent. There is no
+bug at A.
+
+Suppose that in the meantime on the lower line of development somebody
+adds a new calling site for that function at commit Y. The
+commits from Z leading to B all assume the old semantics of that
+function and the callers and the callee are consistent with each
+other. There is no bug at B, either.
+
+Suppose further that the two development lines merge cleanly at C,
+so no conflict resolution is required.
+
+Nevertheless, the code at C is broken, because the callers added
+on the lower line of development have not been converted to the new
+semantics introduced on the upper line of development. So if all
+you know is that D is bad, that Z is good, and that
+linkgit:git-bisect[1] identifies C as the culprit, how will you
+figure out that the problem is due to this change in semantics?
+
+When the result of a git-bisect is a non-merge commit, you should
+normally be able to discover the problem by examining just that commit.
+Developers can make this easy by breaking their changes into small
+self-contained commits. That won't help in the case above, however,
+because the problem isn't obvious from examination of any single
+commit; instead, a global view of the development is required. To
+make matters worse, the change in semantics in the problematic
+function may be just one small part of the changes in the upper
+line of development.
+
+On the other hand, if instead of merging at C you had rebased the
+history between Z to B on top of A, you would have gotten this
+linear history:
+
+................................................................
+ ---Z---o---X--...---o---A---o---o---Y*--...---o---B*--D*
+................................................................
+
+Bisecting between Z and D* would hit a single culprit commit Y*,
+and understanding why Y* was broken would probably be easier.
+
+Partly for this reason, many experienced git users, even when
+working on an otherwise merge-heavy project, keep the history
+linear by rebasing against the latest upstream version before
+publishing.
+
[[advanced-branch-management]]
Advanced branch management
==========================
Fetching individual branches
----------------------------
-Instead of using gitlink:git-remote[1], you can also choose just
+Instead of using linkgit:git-remote[1], you can also choose just
to update one branch at a time, and to store it locally under an
arbitrary name:
We saw above that "origin" is just a shortcut to refer to the
repository that you originally cloned from. This information is
stored in git configuration variables, which you can see using
-gitlink:git-config[1]:
+linkgit:git-config[1]:
-------------------------------------------------
$ git config -l
Also note that all of the above configuration can be performed by
directly editing the file .git/config instead of using
-gitlink:git-config[1].
+linkgit:git-config[1].
-See gitlink:git-config[1] for more details on the configuration
+See linkgit:git-config[1] for more details on the configuration
options mentioned above.
-[[git-internals]]
-Git internals
-=============
+[[git-concepts]]
+Git concepts
+============
+
+Git is built on a small number of simple but powerful ideas. While it
+is possible to get things done without understanding them, you will find
+git much more intuitive if you do.
-Git depends on two fundamental abstractions: the "object database", and
-the "current directory cache" aka "index".
+We start with the most important, the <<def_object_database,object
+database>> and the <<def_index,index>>.
[[the-object-database]]
The Object Database
-------------------
-The object database is literally just a content-addressable collection
-of objects. All objects are named by their content, which is
-approximated by the SHA1 hash of the object itself. Objects may refer
-to other objects (by referencing their SHA1 hash), and so you can
-build up a hierarchy of objects.
-All objects have a statically determined "type" which is
-determined at object creation time, and which identifies the format of
-the object (i.e. how it is used, and how it can refer to other
-objects). There are currently four different object types: "blob",
-"tree", "commit", and "tag".
+We already saw in <<understanding-commits>> that all commits are stored
+under a 40-digit "object name". In fact, all the information needed to
+represent the history of a project is stored in objects with such names.
+In each case the name is calculated by taking the SHA1 hash of the
+contents of the object. The SHA1 hash is a cryptographic hash function.
+What that means to us is that it is impossible to find two different
+objects with the same name. This has a number of advantages; among
+others:
+
+- Git can quickly determine whether two objects are identical or not,
+ just by comparing names.
+- Since object names are computed the same way in every repository, the
+ same content stored in two repositories will always be stored under
+ the same name.
+- Git can detect errors when it reads an object, by checking that the
+ object's name is still the SHA1 hash of its contents.
+
+(See <<object-details>> for the details of the object formatting and
+SHA1 calculation.)
+
+There are four different types of objects: "blob", "tree", "commit", and
+"tag".
+
+- A <<def_blob_object,"blob" object>> is used to store file data.
+- A <<def_tree_object,"tree" object>> is an object that ties one or more
+ "blob" objects into a directory structure. In addition, a tree object
+ can refer to other tree objects, thus creating a directory hierarchy.
+- A <<def_commit_object,"commit" object>> ties such directory hierarchies
+ together into a <<def_DAG,directed acyclic graph>> of revisions--each
+ commit contains the object name of exactly one tree designating the
+ directory hierarchy at the time of the commit. In addition, a commit
+ refers to "parent" commit objects that describe the history of how we
+ arrived at that directory hierarchy.
+- A <<def_tag_object,"tag" object>> symbolically identifies and can be
+ used to sign other objects. It contains the object name and type of
+ another object, a symbolic name (of course!) and, optionally, a
+ signature.
-A <<def_blob_object,"blob" object>> cannot refer to any other object,
-and is, as the name implies, a pure storage object containing some
-user data. It is used to actually store the file data, i.e. a blob
-object is associated with some particular version of some file.
-
-A <<def_tree_object,"tree" object>> is an object that ties one or more
-"blob" objects into a directory structure. In addition, a tree object
-can refer to other tree objects, thus creating a directory hierarchy.
-
-A <<def_commit_object,"commit" object>> ties such directory hierarchies
-together into a <<def_DAG,directed acyclic graph>> of revisions - each
-"commit" is associated with exactly one tree (the directory hierarchy at
-the time of the commit). In addition, a "commit" refers to one or more
-"parent" commit objects that describe the history of how we arrived at
-that directory hierarchy.
-
-As a special case, a commit object with no parents is called the "root"
-commit, and is the point of an initial project commit. Each project
-must have at least one root, and while you can tie several different
-root objects together into one project by creating a commit object which
-has two or more separate roots as its ultimate parents, that's probably
-just going to confuse people. So aim for the notion of "one root object
-per project", even if git itself does not enforce that.
-
-A <<def_tag_object,"tag" object>> symbolically identifies and can be
-used to sign other objects. It contains the identifier and type of
-another object, a symbolic name (of course!) and, optionally, a
-signature.
+The object types in some more detail:
-Regardless of object type, all objects share the following
-characteristics: they are all deflated with zlib, and have a header
-that not only specifies their type, but also provides size information
-about the data in the object. It's worth noting that the SHA1 hash
-that is used to name the object is the hash of the original data
-plus this header, so `sha1sum` 'file' does not match the object name
-for 'file'.
-(Historical note: in the dawn of the age of git the hash
-was the sha1 of the 'compressed' object.)
+[[commit-object]]
+Commit Object
+~~~~~~~~~~~~~
-As a result, the general consistency of an object can always be tested
-independently of the contents or the type of the object: all objects can
-be validated by verifying that (a) their hashes match the content of the
-file and (b) the object successfully inflates to a stream of bytes that
-forms a sequence of <ascii type without space> {plus} <space> {plus} <ascii decimal
-size> {plus} <byte\0> {plus} <binary object data>.
+The "commit" object links a physical state of a tree with a description
+of how we got there and why. Use the --pretty=raw option to
+linkgit:git-show[1] or linkgit:git-log[1] to examine your favorite
+commit:
-The structured objects can further have their structure and
-connectivity to other objects verified. This is generally done with
-the `git-fsck` program, which generates a full dependency graph
-of all objects, and verifies their internal consistency (in addition
-to just verifying their superficial consistency through the hash).
+------------------------------------------------
+$ git show -s --pretty=raw 2be7fcb476
+commit 2be7fcb4764f2dbcee52635b91fedb1b3dcf7ab4
+tree fb3a8bdd0ceddd019615af4d57a53f43d8cee2bf
+parent 257a84d9d02e90447b149af58b271c19405edb6a
+author Dave Watson <dwatson@mimvista.com> 1187576872 -0400
+committer Junio C Hamano <gitster@pobox.com> 1187591163 -0700
-The object types in some more detail:
+ Fix misspelling of 'suppress' in docs
+
+ Signed-off-by: Junio C Hamano <gitster@pobox.com>
+------------------------------------------------
+
+As you can see, a commit is defined by:
+
+- a tree: The SHA1 name of a tree object (as defined below), representing
+ the contents of a directory at a certain point in time.
+- parent(s): The SHA1 name of some number of commits which represent the
+ immediately previous step(s) in the history of the project. The
+ example above has one parent; merge commits may have more than
+ one. A commit with no parents is called a "root" commit, and
+ represents the initial revision of a project. Each project must have
+ at least one root. A project can also have multiple roots, though
+ that isn't common (or necessarily a good idea).
+- an author: The name of the person responsible for this change, together
+ with its date.
+- a committer: The name of the person who actually created the commit,
+ with the date it was done. This may be different from the author, for
+ example, if the author was someone who wrote a patch and emailed it
+ to the person who used it to create the commit.
+- a comment describing this commit.
+
+Note that a commit does not itself contain any information about what
+actually changed; all changes are calculated by comparing the contents
+of the tree referred to by this commit with the trees associated with
+its parents. In particular, git does not attempt to record file renames
+explicitly, though it can identify cases where the existence of the same
+file data at changing paths suggests a rename. (See, for example, the
+-M option to linkgit:git-diff[1]).
+
+A commit is usually created by linkgit:git-commit[1], which creates a
+commit whose parent is normally the current HEAD, and whose tree is
+taken from the content currently stored in the index.
+
+[[tree-object]]
+Tree Object
+~~~~~~~~~~~
+
+The ever-versatile linkgit:git-show[1] command can also be used to
+examine tree objects, but linkgit:git-ls-tree[1] will give you more
+details:
+
+------------------------------------------------
+$ git ls-tree fb3a8bdd0ce
+100644 blob 63c918c667fa005ff12ad89437f2fdc80926e21c .gitignore
+100644 blob 5529b198e8d14decbe4ad99db3f7fb632de0439d .mailmap
+100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3 COPYING
+040000 tree 2fb783e477100ce076f6bf57e4a6f026013dc745 Documentation
+100755 blob 3c0032cec592a765692234f1cba47dfdcc3a9200 GIT-VERSION-GEN
+100644 blob 289b046a443c0647624607d471289b2c7dcd470b INSTALL
+100644 blob 4eb463797adc693dc168b926b6932ff53f17d0b1 Makefile
+100644 blob 548142c327a6790ff8821d67c2ee1eff7a656b52 README
+...
+------------------------------------------------
+
+As you can see, a tree object contains a list of entries, each with a
+mode, object type, SHA1 name, and name, sorted by name. It represents
+the contents of a single directory tree.
+
+The object type may be a blob, representing the contents of a file, or
+another tree, representing the contents of a subdirectory. Since trees
+and blobs, like all other objects, are named by the SHA1 hash of their
+contents, two trees have the same SHA1 name if and only if their
+contents (including, recursively, the contents of all subdirectories)
+are identical. This allows git to quickly determine the differences
+between two related tree objects, since it can ignore any entries with
+identical object names.
+
+(Note: in the presence of submodules, trees may also have commits as
+entries. See <<submodules>> for documentation.)
+
+Note that the files all have mode 644 or 755: git actually only pays
+attention to the executable bit.
[[blob-object]]
Blob Object
------------
+~~~~~~~~~~~
-A "blob" object is nothing but a binary blob of data, and doesn't
-refer to anything else. There is no signature or any other
-verification of the data, so while the object is consistent (it 'is'
-indexed by its sha1 hash, so the data itself is certainly correct), it
-has absolutely no other attributes. No name associations, no
-permissions. It is purely a blob of data (i.e. normally "file
-contents").
+You can use linkgit:git-show[1] to examine the contents of a blob; take,
+for example, the blob in the entry for "COPYING" from the tree above:
-In particular, since the blob is entirely defined by its data, if two
-files in a directory tree (or in multiple different versions of the
-repository) have the same contents, they will share the same blob
-object. The object is totally independent of its location in the
-directory tree, and renaming a file does not change the object that
-file is associated with in any way.
-
-A blob is typically created when gitlink:git-update-index[1]
-is run, and its data can be accessed by gitlink:git-cat-file[1].
+------------------------------------------------
+$ git show 6ff87c4664
-[[tree-object]]
-Tree Object
------------
+ Note that the only valid version of the GPL as far as this project
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+...
+------------------------------------------------
-The next hierarchical object type is the "tree" object. A tree object
-is a list of mode/name/blob data, sorted by name. Alternatively, the
-mode data may specify a directory mode, in which case instead of
-naming a blob, that name is associated with another TREE object.
-
-Like the "blob" object, a tree object is uniquely determined by the
-set contents, and so two separate but identical trees will always
-share the exact same object. This is true at all levels, i.e. it's
-true for a "leaf" tree (which does not refer to any other trees, only
-blobs) as well as for a whole subdirectory.
-
-For that reason a "tree" object is just a pure data abstraction: it
-has no history, no signatures, no verification of validity, except
-that since the contents are again protected by the hash itself, we can
-trust that the tree is immutable and its contents never change.
-
-So you can trust the contents of a tree to be valid, the same way you
-can trust the contents of a blob, but you don't know where those
-contents 'came' from.
-
-Side note on trees: since a "tree" object is a sorted list of
-"filename+content", you can create a diff between two trees without
-actually having to unpack two trees. Just ignore all common parts,
-and your diff will look right. In other words, you can effectively
-(and efficiently) tell the difference between any two random trees by
-O(n) where "n" is the size of the difference, rather than the size of
-the tree.
-
-Side note 2 on trees: since the name of a "blob" depends entirely and
-exclusively on its contents (i.e. there are no names or permissions
-involved), you can see trivial renames or permission changes by
-noticing that the blob stayed the same. However, renames with data
-changes need a smarter "diff" implementation.
-
-A tree is created with gitlink:git-write-tree[1] and
-its data can be accessed by gitlink:git-ls-tree[1].
-Two trees can be compared with gitlink:git-diff-tree[1].
+A "blob" object is nothing but a binary blob of data. It doesn't refer
+to anything else or have attributes of any kind.
-[[commit-object]]
-Commit Object
--------------
+Since the blob is entirely defined by its data, if two files in a
+directory tree (or in multiple different versions of the repository)
+have the same contents, they will share the same blob object. The object
+is totally independent of its location in the directory tree, and
+renaming a file does not change the object that file is associated with.
-The "commit" object is an object that introduces the notion of
-history into the picture. In contrast to the other objects, it
-doesn't just describe the physical state of a tree, it describes how
-we got there, and why.
-
-A "commit" is defined by the tree-object that it results in, the
-parent commits (zero, one or more) that led up to that point, and a
-comment on what happened. Again, a commit is not trusted per se:
-the contents are well-defined and "safe" due to the cryptographically
-strong signatures at all levels, but there is no reason to believe
-that the tree is "good" or that the merge information makes sense.
-The parents do not have to actually have any relationship with the
-result, for example.
-
-Note on commits: unlike some SCM's, commits do not contain
-rename information or file mode change information. All of that is
-implicit in the trees involved (the result tree, and the result trees
-of the parents), and describing that makes no sense in this idiotic
-file manager.
-
-A commit is created with gitlink:git-commit-tree[1] and
-its data can be accessed by gitlink:git-cat-file[1].
+Note that any tree or blob object can be examined using
+linkgit:git-show[1] with the <revision>:<path> syntax. This can
+sometimes be useful for browsing the contents of a tree that is not
+currently checked out.
[[trust]]
Trust
------
+~~~~~
-An aside on the notion of "trust". Trust is really outside the scope
-of "git", but it's worth noting a few things. First off, since
-everything is hashed with SHA1, you 'can' trust that an object is
-intact and has not been messed with by external sources. So the name
-of an object uniquely identifies a known state - just not a state that
-you may want to trust.
+If you receive the SHA1 name of a blob from one source, and its contents
+from another (possibly untrusted) source, you can still trust that those
+contents are correct as long as the SHA1 name agrees. This is because
+the SHA1 is designed so that it is infeasible to find different contents
+that produce the same hash.
-Furthermore, since the SHA1 signature of a commit refers to the
-SHA1 signatures of the tree it is associated with and the signatures
-of the parent, a single named commit specifies uniquely a whole set
-of history, with full contents. You can't later fake any step of the
-way once you have the name of a commit.
+Similarly, you need only trust the SHA1 name of a top-level tree object
+to trust the contents of the entire directory that it refers to, and if
+you receive the SHA1 name of a commit from a trusted source, then you
+can easily verify the entire history of commits reachable through
+parents of that commit, and all of those contents of the trees referred
+to by those commits.
So to introduce some real trust in the system, the only thing you need
to do is to digitally sign just 'one' special note, which includes the
[[tag-object]]
Tag Object
-----------
+~~~~~~~~~~
-Git provides the "tag" object to simplify creating, managing and
-exchanging symbolic and signed tokens. The "tag" object at its
-simplest simply symbolically identifies another object by containing
-the sha1, type and symbolic name.
+A tag object contains an object, object type, tag name, the name of the
+person ("tagger") who created the tag, and a message, which may contain
+a signature, as can be seen using the linkgit:git-cat-file[1]:
-However it can optionally contain additional signature information
-(which git doesn't care about as long as there's less than 8k of
-it). This can then be verified externally to git.
+------------------------------------------------
+$ git cat-file tag v1.5.0
+object 437b1b20df4b356c9342dac8d38849f24ef44f27
+type commit
+tag v1.5.0
+tagger Junio C Hamano <junkio@cox.net> 1171411200 +0000
+
+GIT 1.5.0
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQBF0lGqwMbZpPMRm5oRAuRiAJ9ohBLd7s2kqjkKlq1qqC57SbnmzQCdG4ui
+nLE/L9aUXdWeTFPron96DLA=
+=2E+0
+-----END PGP SIGNATURE-----
+------------------------------------------------
-Note that despite the tag features, "git" itself only handles content
-integrity; the trust framework (and signature provision and
-verification) has to come from outside.
+See the linkgit:git-tag[1] command to learn how to create and verify tag
+objects. (Note that linkgit:git-tag[1] can also be used to create
+"lightweight tags", which are not tag objects at all, but just simple
+references whose names begin with "refs/tags/").
-A tag is created with gitlink:git-mktag[1],
-its data can be accessed by gitlink:git-cat-file[1],
-and the signature can be verified by
-gitlink:git-verify-tag[1].
+[[pack-files]]
+How git stores objects efficiently: pack files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Newly created objects are initially created in a file named after the
+object's SHA1 hash (stored in .git/objects).
-[[the-index]]
-The "index" aka "Current Directory Cache"
------------------------------------------
+Unfortunately this system becomes inefficient once a project has a
+lot of objects. Try this on an old project:
-The index is a simple binary file, which contains an efficient
-representation of the contents of a virtual directory. It
-does so by a simple array that associates a set of names, dates,
-permissions and content (aka "blob") objects together. The cache is
-always kept ordered by name, and names are unique (with a few very
-specific rules) at any point in time, but the cache has no long-term
-meaning, and can be partially updated at any time.
-
-In particular, the index certainly does not need to be consistent with
-the current directory contents (in fact, most operations will depend on
-different ways to make the index 'not' be consistent with the directory
-hierarchy), but it has three very important attributes:
-
-'(a) it can re-generate the full state it caches (not just the
-directory structure: it contains pointers to the "blob" objects so
-that it can regenerate the data too)'
-
-As a special case, there is a clear and unambiguous one-way mapping
-from a current directory cache to a "tree object", which can be
-efficiently created from just the current directory cache without
-actually looking at any other data. So a directory cache at any one
-time uniquely specifies one and only one "tree" object (but has
-additional data to make it easy to match up that tree object with what
-has happened in the directory)
-
-'(b) it has efficient methods for finding inconsistencies between that
-cached state ("tree object waiting to be instantiated") and the
-current state.'
-
-'(c) it can additionally efficiently represent information about merge
-conflicts between different tree objects, allowing each pathname to be
-associated with sufficient information about the trees involved that
-you can create a three-way merge between them.'
+------------------------------------------------
+$ git count-objects
+6930 objects, 47620 kilobytes
+------------------------------------------------
-Those are the ONLY three things that the directory cache does. It's a
-cache, and the normal operation is to re-generate it completely from a
-known tree object, or update/compare it with a live tree that is being
-developed. If you blow the directory cache away entirely, you generally
-haven't lost any information as long as you have the name of the tree
-that it described.
+The first number is the number of objects which are kept in
+individual files. The second is the amount of space taken up by
+those "loose" objects.
-At the same time, the index is also the staging area for creating
-new trees, and creating a new tree always involves a controlled
-modification of the index file. In particular, the index file can
-have the representation of an intermediate tree that has not yet been
-instantiated. So the index can be thought of as a write-back cache,
-which can contain dirty information that has not yet been written back
-to the backing store.
+You can save space and make git faster by moving these loose objects in
+to a "pack file", which stores a group of objects in an efficient
+compressed format; the details of how pack files are formatted can be
+found in link:technical/pack-format.txt[technical/pack-format.txt].
+To put the loose objects into a pack, just run git repack:
+------------------------------------------------
+$ git repack
+Generating pack...
+Done counting 6020 objects.
+Deltifying 6020 objects.
+ 100% (6020/6020) done
+Writing 6020 objects.
+ 100% (6020/6020) done
+Total 6020, written 6020 (delta 4070), reused 0 (delta 0)
+Pack pack-3e54ad29d5b2e05838c75df582c65257b8d08e1c created.
+------------------------------------------------
-[[the-workflow]]
-The Workflow
-------------
+You can then run
-Generally, all "git" operations work on the index file. Some operations
-work *purely* on the index file (showing the current state of the
-index), but most operations move data to and from the index file. Either
-from the database or from the working directory. Thus there are four
-main combinations:
+------------------------------------------------
+$ git prune
+------------------------------------------------
-[[working-directory-to-index]]
-working directory -> index
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+to remove any of the "loose" objects that are now contained in the
+pack. This will also remove any unreferenced objects (which may be
+created when, for example, you use "git reset" to remove a commit).
+You can verify that the loose objects are gone by looking at the
+.git/objects directory or by running
-You update the index with information from the working directory with
-the gitlink:git-update-index[1] command. You
-generally update the index information by just specifying the filename
-you want to update, like so:
+------------------------------------------------
+$ git count-objects
+0 objects, 0 kilobytes
+------------------------------------------------
--------------------------------------------------
-$ git-update-index filename
--------------------------------------------------
+Although the object files are gone, any commands that refer to those
+objects will work exactly as they did before.
-but to avoid common mistakes with filename globbing etc, the command
-will not normally add totally new entries or remove old entries,
-i.e. it will normally just update existing cache entries.
+The linkgit:git-gc[1] command performs packing, pruning, and more for
+you, so is normally the only high-level command you need.
-To tell git that yes, you really do realize that certain files no
-longer exist, or that new files should be added, you
-should use the `--remove` and `--add` flags respectively.
+[[dangling-objects]]
+Dangling objects
+~~~~~~~~~~~~~~~~
-NOTE! A `--remove` flag does 'not' mean that subsequent filenames will
-necessarily be removed: if the files still exist in your directory
-structure, the index will be updated with their new status, not
-removed. The only thing `--remove` means is that update-cache will be
-considering a removed file to be a valid thing, and if the file really
-does not exist any more, it will update the index accordingly.
+The linkgit:git-fsck[1] command will sometimes complain about dangling
+objects. They are not a problem.
-As a special case, you can also do `git-update-index --refresh`, which
-will refresh the "stat" information of each index to match the current
-stat information. It will 'not' update the object status itself, and
-it will only update the fields that are used to quickly test whether
-an object still matches its old backing store object.
+The most common cause of dangling objects is that you've rebased a
+branch, or you have pulled from somebody else who rebased a branch--see
+<<cleaning-up-history>>. In that case, the old head of the original
+branch still exists, as does everything it pointed to. The branch
+pointer itself just doesn't, since you replaced it with another one.
-[[index-to-object-database]]
-index -> object database
-~~~~~~~~~~~~~~~~~~~~~~~~
+There are also other situations that cause dangling objects. For
+example, a "dangling blob" may arise because you did a "git add" of a
+file, but then, before you actually committed it and made it part of the
+bigger picture, you changed something else in that file and committed
+that *updated* thing--the old state that you added originally ends up
+not being pointed to by any commit or tree, so it's now a dangling blob
+object.
-You write your current index file to a "tree" object with the program
+Similarly, when the "recursive" merge strategy runs, and finds that
+there are criss-cross merges and thus more than one merge base (which is
+fairly unusual, but it does happen), it will generate one temporary
+midway tree (or possibly even more, if you had lots of criss-crossing
+merges and more than two merge bases) as a temporary internal merge
+base, and again, those are real objects, but the end result will not end
+up pointing to them, so they end up "dangling" in your repository.
--------------------------------------------------
-$ git-write-tree
--------------------------------------------------
+Generally, dangling objects aren't anything to worry about. They can
+even be very useful: if you screw something up, the dangling objects can
+be how you recover your old tree (say, you did a rebase, and realized
+that you really didn't want to--you can look at what dangling objects
+you have, and decide to reset your head to some old dangling state).
-that doesn't come with any options - it will just write out the
-current index into the set of tree objects that describe that state,
-and it will return the name of the resulting top-level tree. You can
-use that tree to re-generate the index at any time by going in the
-other direction:
+For commits, you can just use:
-[[object-database-to-index]]
-object database -> index
-~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------
+$ gitk <dangling-commit-sha-goes-here> --not --all
+------------------------------------------------
-You read a "tree" file from the object database, and use that to
-populate (and overwrite - don't do this if your index contains any
-unsaved state that you might want to restore later!) your current
-index. Normal operation is just
+This asks for all the history reachable from the given commit but not
+from any branch, tag, or other reference. If you decide it's something
+you want, you can always create a new reference to it, e.g.,
--------------------------------------------------
-$ git-read-tree <sha1 of tree>
--------------------------------------------------
+------------------------------------------------
+$ git branch recovered-branch <dangling-commit-sha-goes-here>
+------------------------------------------------
-and your index file will now be equivalent to the tree that you saved
-earlier. However, that is only your 'index' file: your working
-directory contents have not been modified.
+For blobs and trees, you can't do the same, but you can still examine
+them. You can just do
-[[index-to-working-directory]]
-index -> working directory
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------------
+$ git show <dangling-blob/tree-sha-goes-here>
+------------------------------------------------
-You update your working directory from the index by "checking out"
-files. This is not a very common operation, since normally you'd just
-keep your files updated, and rather than write to your working
-directory, you'd tell the index files about the changes in your
-working directory (i.e. `git-update-index`).
+to show what the contents of the blob were (or, for a tree, basically
+what the "ls" for that directory was), and that may give you some idea
+of what the operation was that left that dangling object.
-However, if you decide to jump to a new version, or check out somebody
-else's version, or just restore a previous tree, you'd populate your
-index file with read-tree, and then you need to check out the result
-with
+Usually, dangling blobs and trees aren't very interesting. They're
+almost always the result of either being a half-way mergebase (the blob
+will often even have the conflict markers from a merge in it, if you
+have had conflicting merges that you fixed up by hand), or simply
+because you interrupted a "git fetch" with ^C or something like that,
+leaving _some_ of the new objects in the object database, but just
+dangling and useless.
--------------------------------------------------
-$ git-checkout-index filename
--------------------------------------------------
+Anyway, once you are sure that you're not interested in any dangling
+state, you can just prune all unreachable objects:
-or, if you want to check out all of the index, use `-a`.
+------------------------------------------------
+$ git prune
+------------------------------------------------
+
+and they'll be gone. But you should only run "git prune" on a quiescent
+repository--it's kind of like doing a filesystem fsck recovery: you
+don't want to do that while the filesystem is mounted.
+
+(The same is true of "git-fsck" itself, btw, but since
+git-fsck never actually *changes* the repository, it just reports
+on what it found, git-fsck itself is never "dangerous" to run.
+Running it while somebody is actually changing the repository can cause
+confusing and scary messages, but it won't actually do anything bad. In
+contrast, running "git prune" while somebody is actively changing the
+repository is a *BAD* idea).
+
+[[recovering-from-repository-corruption]]
+Recovering from repository corruption
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By design, git treats data trusted to it with caution. However, even in
+the absence of bugs in git itself, it is still possible that hardware or
+operating system errors could corrupt data.
+
+The first defense against such problems is backups. You can back up a
+git directory using clone, or just using cp, tar, or any other backup
+mechanism.
+
+As a last resort, you can search for the corrupted objects and attempt
+to replace them by hand. Back up your repository before attempting this
+in case you corrupt things even more in the process.
+
+We'll assume that the problem is a single missing or corrupted blob,
+which is sometimes a solvable problem. (Recovering missing trees and
+especially commits is *much* harder).
+
+Before starting, verify that there is corruption, and figure out where
+it is with linkgit:git-fsck[1]; this may be time-consuming.
+
+Assume the output looks like this:
+
+------------------------------------------------
+$ git-fsck --full
+broken link from tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
+ to blob 4b9458b3786228369c63936db65827de3cc06200
+missing blob 4b9458b3786228369c63936db65827de3cc06200
+------------------------------------------------
+
+(Typically there will be some "dangling object" messages too, but they
+aren't interesting.)
+
+Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6
+points to it. If you could find just one copy of that missing blob
+object, possibly in some other repository, you could move it into
+.git/objects/4b/9458b3... and be done. Suppose you can't. You can
+still examine the tree that pointed to it with linkgit:git-ls-tree[1],
+which might output something like:
+
+------------------------------------------------
+$ git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
+100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8 .gitignore
+100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883 .mailmap
+100644 blob ca442d313d86dc67e0a2e5d584b465bd382cbf5c COPYING
+...
+100644 blob 4b9458b3786228369c63936db65827de3cc06200 myfile
+...
+------------------------------------------------
+
+So now you know that the missing blob was the data for a file named
+"myfile". And chances are you can also identify the directory--let's
+say it's in "somedirectory". If you're lucky the missing copy might be
+the same as the copy you have checked out in your working tree at
+"somedirectory/myfile"; you can test whether that's right with
+linkgit:git-hash-object[1]:
+
+------------------------------------------------
+$ git hash-object -w somedirectory/myfile
+------------------------------------------------
+
+which will create and store a blob object with the contents of
+somedirectory/myfile, and output the sha1 of that object. if you're
+extremely lucky it might be 4b9458b3786228369c63936db65827de3cc06200, in
+which case you've guessed right, and the corruption is fixed!
+
+Otherwise, you need more information. How do you tell which version of
+the file has been lost?
+
+The easiest way to do this is with:
+
+------------------------------------------------
+$ git log --raw --all --full-history -- somedirectory/myfile
+------------------------------------------------
+
+Because you're asking for raw output, you'll now get something like
+
+------------------------------------------------
+commit abc
+Author:
+Date:
+...
+:100644 100644 4b9458b... newsha... M somedirectory/myfile
+
+
+commit xyz
+Author:
+Date:
+
+...
+:100644 100644 oldsha... 4b9458b... M somedirectory/myfile
+------------------------------------------------
+
+This tells you that the immediately preceding version of the file was
+"newsha", and that the immediately following version was "oldsha".
+You also know the commit messages that went with the change from oldsha
+to 4b9458b and with the change from 4b9458b to newsha.
+
+If you've been committing small enough changes, you may now have a good
+shot at reconstructing the contents of the in-between state 4b9458b.
+
+If you can do that, you can now recreate the missing object with
+
+------------------------------------------------
+$ git hash-object -w <recreated-file>
+------------------------------------------------
+
+and your repository is good again!
+
+(Btw, you could have ignored the fsck, and started with doing a
+
+------------------------------------------------
+$ git log --raw --all
+------------------------------------------------
+
+and just looked for the sha of the missing object (4b9458b..) in that
+whole thing. It's up to you - git does *have* a lot of information, it is
+just missing one particular blob version.
+
+[[the-index]]
+The index
+-----------
+
+The index is a binary file (generally kept in .git/index) containing a
+sorted list of path names, each with permissions and the SHA1 of a blob
+object; linkgit:git-ls-files[1] can show you the contents of the index:
+
+-------------------------------------------------
+$ git ls-files --stage
+100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0 .gitignore
+100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0 .mailmap
+100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0 COPYING
+100644 a37b2152bd26be2c2289e1f57a292534a51a93c7 0 Documentation/.gitignore
+100644 fbefe9a45b00a54b58d94d06eca48b03d40a50e0 0 Documentation/Makefile
+...
+100644 2511aef8d89ab52be5ec6a5e46236b4b6bcd07ea 0 xdiff/xtypes.h
+100644 2ade97b2574a9f77e7ae4002a4e07a6a38e46d07 0 xdiff/xutils.c
+100644 d5de8292e05e7c36c4b68857c1cf9855e3d2f70a 0 xdiff/xutils.h
+-------------------------------------------------
+
+Note that in older documentation you may see the index called the
+"current directory cache" or just the "cache". It has three important
+properties:
+
+1. The index contains all the information necessary to generate a single
+(uniquely determined) tree object.
++
+For example, running linkgit:git-commit[1] generates this tree object
+from the index, stores it in the object database, and uses it as the
+tree object associated with the new commit.
+
+2. The index enables fast comparisons between the tree object it defines
+and the working tree.
++
+It does this by storing some additional data for each entry (such as
+the last modified time). This data is not displayed above, and is not
+stored in the created tree object, but it can be used to determine
+quickly which files in the working directory differ from what was
+stored in the index, and thus save git from having to read all of the
+data from such files to look for changes.
+
+3. It can efficiently represent information about merge conflicts
+between different tree objects, allowing each pathname to be
+associated with sufficient information about the trees involved that
+you can create a three-way merge between them.
++
+We saw in <<conflict-resolution>> that during a merge the index can
+store multiple versions of a single file (called "stages"). The third
+column in the linkgit:git-ls-files[1] output above is the stage
+number, and will take on values other than 0 for files with merge
+conflicts.
+
+The index is thus a sort of temporary staging area, which is filled with
+a tree which you are in the process of working on.
+
+If you blow the index away entirely, you generally haven't lost any
+information as long as you have the name of the tree that it described.
+
+[[submodules]]
+Submodules
+==========
+
+Large projects are often composed of smaller, self-contained modules. For
+example, an embedded Linux distribution's source tree would include every
+piece of software in the distribution with some local modifications; a movie
+player might need to build against a specific, known-working version of a
+decompression library; several independent programs might all share the same
+build scripts.
+
+With centralized revision control systems this is often accomplished by
+including every module in one single repository. Developers can check out
+all modules or only the modules they need to work with. They can even modify
+files across several modules in a single commit while moving things around
+or updating APIs and translations.
+
+Git does not allow partial checkouts, so duplicating this approach in Git
+would force developers to keep a local copy of modules they are not
+interested in touching. Commits in an enormous checkout would be slower
+than you'd expect as Git would have to scan every directory for changes.
+If modules have a lot of local history, clones would take forever.
+
+On the plus side, distributed revision control systems can much better
+integrate with external sources. In a centralized model, a single arbitrary
+snapshot of the external project is exported from its own revision control
+and then imported into the local revision control on a vendor branch. All
+the history is hidden. With distributed revision control you can clone the
+entire external history and much more easily follow development and re-merge
+local changes.
+
+Git's submodule support allows a repository to contain, as a subdirectory, a
+checkout of an external project. Submodules maintain their own identity;
+the submodule support just stores the submodule repository location and
+commit ID, so other developers who clone the containing project
+("superproject") can easily clone all the submodules at the same revision.
+Partial checkouts of the superproject are possible: you can tell Git to
+clone none, some or all of the submodules.
+
+The linkgit:git-submodule[1] command is available since Git 1.5.3. Users
+with Git 1.5.2 can look up the submodule commits in the repository and
+manually check them out; earlier versions won't recognize the submodules at
+all.
+
+To see how submodule support works, create (for example) four example
+repositories that can be used later as a submodule:
+
+-------------------------------------------------
+$ mkdir ~/git
+$ cd ~/git
+$ for i in a b c d
+do
+ mkdir $i
+ cd $i
+ git init
+ echo "module $i" > $i.txt
+ git add $i.txt
+ git commit -m "Initial commit, submodule $i"
+ cd ..
+done
+-------------------------------------------------
+
+Now create the superproject and add all the submodules:
+
+-------------------------------------------------
+$ mkdir super
+$ cd super
+$ git init
+$ for i in a b c d
+do
+ git submodule add ~/git/$i
+done
+-------------------------------------------------
+
+NOTE: Do not use local URLs here if you plan to publish your superproject!
+
+See what files `git submodule` created:
+
+-------------------------------------------------
+$ ls -a
+. .. .git .gitmodules a b c d
+-------------------------------------------------
+
+The `git submodule add` command does a couple of things:
+
+- It clones the submodule under the current directory and by default checks out
+ the master branch.
+- It adds the submodule's clone path to the linkgit:gitmodules[5] file and
+ adds this file to the index, ready to be committed.
+- It adds the submodule's current commit ID to the index, ready to be
+ committed.
+
+Commit the superproject:
+
+-------------------------------------------------
+$ git commit -m "Add submodules a, b, c and d."
+-------------------------------------------------
+
+Now clone the superproject:
+
+-------------------------------------------------
+$ cd ..
+$ git clone super cloned
+$ cd cloned
+-------------------------------------------------
+
+The submodule directories are there, but they're empty:
+
+-------------------------------------------------
+$ ls -a a
+. ..
+$ git submodule status
+-d266b9873ad50488163457f025db7cdd9683d88b a
+-e81d457da15309b4fef4249aba9b50187999670d b
+-c1536a972b9affea0f16e0680ba87332dc059146 c
+-d96249ff5d57de5de093e6baff9e0aafa5276a74 d
+-------------------------------------------------
+
+NOTE: The commit object names shown above would be different for you, but they
+should match the HEAD commit object names of your repositories. You can check
+it by running `git ls-remote ../a`.
+
+Pulling down the submodules is a two-step process. First run `git submodule
+init` to add the submodule repository URLs to `.git/config`:
+
+-------------------------------------------------
+$ git submodule init
+-------------------------------------------------
+
+Now use `git submodule update` to clone the repositories and check out the
+commits specified in the superproject:
+
+-------------------------------------------------
+$ git submodule update
+$ cd a
+$ ls -a
+. .. .git a.txt
+-------------------------------------------------
+
+One major difference between `git submodule update` and `git submodule add` is
+that `git submodule update` checks out a specific commit, rather than the tip
+of a branch. It's like checking out a tag: the head is detached, so you're not
+working on a branch.
+
+-------------------------------------------------
+$ git branch
+* (no branch)
+ master
+-------------------------------------------------
+
+If you want to make a change within a submodule and you have a detached head,
+then you should create or checkout a branch, make your changes, publish the
+change within the submodule, and then update the superproject to reference the
+new commit:
+
+-------------------------------------------------
+$ git checkout master
+-------------------------------------------------
+
+or
+
+-------------------------------------------------
+$ git checkout -b fix-up
+-------------------------------------------------
+
+then
+
+-------------------------------------------------
+$ echo "adding a line again" >> a.txt
+$ git commit -a -m "Updated the submodule from within the superproject."
+$ git push
+$ cd ..
+$ git diff
+diff --git a/a b/a
+index d266b98..261dfac 160000
+--- a/a
++++ b/a
+@@ -1 +1 @@
+-Subproject commit d266b9873ad50488163457f025db7cdd9683d88b
++Subproject commit 261dfac35cb99d380eb966e102c1197139f7fa24
+$ git add a
+$ git commit -m "Updated submodule a."
+$ git push
+-------------------------------------------------
+
+You have to run `git submodule update` after `git pull` if you want to update
+submodules, too.
+
+Pitfalls with submodules
+------------------------
+
+Always publish the submodule change before publishing the change to the
+superproject that references it. If you forget to publish the submodule change,
+others won't be able to clone the repository:
+
+-------------------------------------------------
+$ cd ~/git/super/a
+$ echo i added another line to this file >> a.txt
+$ git commit -a -m "doing it wrong this time"
+$ cd ..
+$ git add a
+$ git commit -m "Updated submodule a again."
+$ git push
+$ cd ~/git/cloned
+$ git pull
+$ git submodule update
+error: pathspec '261dfac35cb99d380eb966e102c1197139f7fa24' did not match any file(s) known to git.
+Did you forget to 'git add'?
+Unable to checkout '261dfac35cb99d380eb966e102c1197139f7fa24' in submodule path 'a'
+-------------------------------------------------
+
+You also should not rewind branches in a submodule beyond commits that were
+ever recorded in any superproject.
+
+It's not safe to run `git submodule update` if you've made and committed
+changes within a submodule without checking out a branch first. They will be
+silently overwritten:
+
+-------------------------------------------------
+$ cat a.txt
+module a
+$ echo line added from private2 >> a.txt
+$ git commit -a -m "line added inside private2"
+$ cd ..
+$ git submodule update
+Submodule path 'a': checked out 'd266b9873ad50488163457f025db7cdd9683d88b'
+$ cd a
+$ cat a.txt
+module a
+-------------------------------------------------
+
+NOTE: The changes are still visible in the submodule's reflog.
+
+This is not the case if you did not commit your changes.
+
+[[low-level-operations]]
+Low-level git operations
+========================
+
+Many of the higher-level commands were originally implemented as shell
+scripts using a smaller core of low-level git commands. These can still
+be useful when doing unusual things with git, or just as a way to
+understand its inner workings.
+
+[[object-manipulation]]
+Object access and manipulation
+------------------------------
+
+The linkgit:git-cat-file[1] command can show the contents of any object,
+though the higher-level linkgit:git-show[1] is usually more useful.
+
+The linkgit:git-commit-tree[1] command allows constructing commits with
+arbitrary parents and trees.
+
+A tree can be created with linkgit:git-write-tree[1] and its data can be
+accessed by linkgit:git-ls-tree[1]. Two trees can be compared with
+linkgit:git-diff-tree[1].
+
+A tag is created with linkgit:git-mktag[1], and the signature can be
+verified by linkgit:git-verify-tag[1], though it is normally simpler to
+use linkgit:git-tag[1] for both.
+
+[[the-workflow]]
+The Workflow
+------------
+
+High-level operations such as linkgit:git-commit[1],
+linkgit:git-checkout[1] and linkgit:git-reset[1] work by moving data
+between the working tree, the index, and the object database. Git
+provides low-level operations which perform each of these steps
+individually.
+
+Generally, all "git" operations work on the index file. Some operations
+work *purely* on the index file (showing the current state of the
+index), but most operations move data between the index file and either
+the database or the working directory. Thus there are four main
+combinations:
+
+[[working-directory-to-index]]
+working directory -> index
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The linkgit:git-update-index[1] command updates the index with
+information from the working directory. You generally update the
+index information by just specifying the filename you want to update,
+like so:
+
+-------------------------------------------------
+$ git update-index filename
+-------------------------------------------------
+
+but to avoid common mistakes with filename globbing etc, the command
+will not normally add totally new entries or remove old entries,
+i.e. it will normally just update existing cache entries.
+
+To tell git that yes, you really do realize that certain files no
+longer exist, or that new files should be added, you
+should use the `--remove` and `--add` flags respectively.
+
+NOTE! A `--remove` flag does 'not' mean that subsequent filenames will
+necessarily be removed: if the files still exist in your directory
+structure, the index will be updated with their new status, not
+removed. The only thing `--remove` means is that update-index will be
+considering a removed file to be a valid thing, and if the file really
+does not exist any more, it will update the index accordingly.
+
+As a special case, you can also do `git-update-index --refresh`, which
+will refresh the "stat" information of each index to match the current
+stat information. It will 'not' update the object status itself, and
+it will only update the fields that are used to quickly test whether
+an object still matches its old backing store object.
+
+The previously introduced linkgit:git-add[1] is just a wrapper for
+linkgit:git-update-index[1].
+
+[[index-to-object-database]]
+index -> object database
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+You write your current index file to a "tree" object with the program
+
+-------------------------------------------------
+$ git write-tree
+-------------------------------------------------
+
+that doesn't come with any options--it will just write out the
+current index into the set of tree objects that describe that state,
+and it will return the name of the resulting top-level tree. You can
+use that tree to re-generate the index at any time by going in the
+other direction:
+
+[[object-database-to-index]]
+object database -> index
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+You read a "tree" file from the object database, and use that to
+populate (and overwrite--don't do this if your index contains any
+unsaved state that you might want to restore later!) your current
+index. Normal operation is just
+
+-------------------------------------------------
+$ git-read-tree <sha1 of tree>
+-------------------------------------------------
+
+and your index file will now be equivalent to the tree that you saved
+earlier. However, that is only your 'index' file: your working
+directory contents have not been modified.
+
+[[index-to-working-directory]]
+index -> working directory
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You update your working directory from the index by "checking out"
+files. This is not a very common operation, since normally you'd just
+keep your files updated, and rather than write to your working
+directory, you'd tell the index files about the changes in your
+working directory (i.e. `git-update-index`).
+
+However, if you decide to jump to a new version, or check out somebody
+else's version, or just restore a previous tree, you'd populate your
+index file with read-tree, and then you need to check out the result
+with
+
+-------------------------------------------------
+$ git-checkout-index filename
+-------------------------------------------------
+
+or, if you want to check out all of the index, use `-a`.
NOTE! git-checkout-index normally refuses to overwrite old files, so
if you have an old version of the tree already checked out, you will
To commit a tree you have instantiated with "git-write-tree", you'd
create a "commit" object that refers to that tree and the history
-behind it - most notably the "parent" commits that preceded it in
+behind it--most notably the "parent" commits that preceded it in
history.
Normally a "commit" has one parent: the previous state of the tree
You can examine the data represented in the object database and the
index with various helper tools. For every object, you can use
-gitlink:git-cat-file[1] to examine details about the
+linkgit:git-cat-file[1] to examine details about the
object:
-------------------------------------------------
tree, aka the common tree, and the two "result" trees, aka the branches
you want to merge), you do a "merge" read into the index. This will
complain if it has to throw away your old index contents, so you should
-make sure that you've committed those - in fact you would normally
+make sure that you've committed those--in fact you would normally
always do a merge against your last commit (which should thus match what
you have in your current index anyway).
---------------------------------
Sadly, many merges aren't trivial. If there are files that have
-been added.moved or removed, or if both branches have modified the
+been added, moved or removed, or if both branches have modified the
same file, you will be left with an index tree that contains "merge
entries" in it. Such an index tree can 'NOT' be written out to a tree
object, and you will have to resolve any such merge clashes using
and that is what higher level `git merge -s resolve` is implemented with.
-[[pack-files]]
-How git stores objects efficiently: pack files
-----------------------------------------------
-
-We've seen how git stores each object in a file named after the
-object's SHA1 hash.
-
-Unfortunately this system becomes inefficient once a project has a
-lot of objects. Try this on an old project:
+[[hacking-git]]
+Hacking git
+===========
-------------------------------------------------
-$ git count-objects
-6930 objects, 47620 kilobytes
-------------------------------------------------
-
-The first number is the number of objects which are kept in
-individual files. The second is the amount of space taken up by
-those "loose" objects.
-
-You can save space and make git faster by moving these loose objects in
-to a "pack file", which stores a group of objects in an efficient
-compressed format; the details of how pack files are formatted can be
-found in link:technical/pack-format.txt[technical/pack-format.txt].
-
-To put the loose objects into a pack, just run git repack:
-
-------------------------------------------------
-$ git repack
-Generating pack...
-Done counting 6020 objects.
-Deltifying 6020 objects.
- 100% (6020/6020) done
-Writing 6020 objects.
- 100% (6020/6020) done
-Total 6020, written 6020 (delta 4070), reused 0 (delta 0)
-Pack pack-3e54ad29d5b2e05838c75df582c65257b8d08e1c created.
-------------------------------------------------
-
-You can then run
-
-------------------------------------------------
-$ git prune
-------------------------------------------------
-
-to remove any of the "loose" objects that are now contained in the
-pack. This will also remove any unreferenced objects (which may be
-created when, for example, you use "git reset" to remove a commit).
-You can verify that the loose objects are gone by looking at the
-.git/objects directory or by running
-
-------------------------------------------------
-$ git count-objects
-0 objects, 0 kilobytes
-------------------------------------------------
-
-Although the object files are gone, any commands that refer to those
-objects will work exactly as they did before.
-
-The gitlink:git-gc[1] command performs packing, pruning, and more for
-you, so is normally the only high-level command you need.
-
-[[dangling-objects]]
-Dangling objects
-----------------
+This chapter covers internal details of the git implementation which
+probably only git developers need to understand.
-The gitlink:git-fsck[1] command will sometimes complain about dangling
-objects. They are not a problem.
-
-The most common cause of dangling objects is that you've rebased a
-branch, or you have pulled from somebody else who rebased a branch--see
-<<cleaning-up-history>>. In that case, the old head of the original
-branch still exists, as does everything it pointed to. The branch
-pointer itself just doesn't, since you replaced it with another one.
-
-There are also other situations that cause dangling objects. For
-example, a "dangling blob" may arise because you did a "git add" of a
-file, but then, before you actually committed it and made it part of the
-bigger picture, you changed something else in that file and committed
-that *updated* thing - the old state that you added originally ends up
-not being pointed to by any commit or tree, so it's now a dangling blob
-object.
-
-Similarly, when the "recursive" merge strategy runs, and finds that
-there are criss-cross merges and thus more than one merge base (which is
-fairly unusual, but it does happen), it will generate one temporary
-midway tree (or possibly even more, if you had lots of criss-crossing
-merges and more than two merge bases) as a temporary internal merge
-base, and again, those are real objects, but the end result will not end
-up pointing to them, so they end up "dangling" in your repository.
-
-Generally, dangling objects aren't anything to worry about. They can
-even be very useful: if you screw something up, the dangling objects can
-be how you recover your old tree (say, you did a rebase, and realized
-that you really didn't want to - you can look at what dangling objects
-you have, and decide to reset your head to some old dangling state).
-
-For commits, you can just use:
-
-------------------------------------------------
-$ gitk <dangling-commit-sha-goes-here> --not --all
-------------------------------------------------
-
-This asks for all the history reachable from the given commit but not
-from any branch, tag, or other reference. If you decide it's something
-you want, you can always create a new reference to it, e.g.,
-
-------------------------------------------------
-$ git branch recovered-branch <dangling-commit-sha-goes-here>
-------------------------------------------------
-
-For blobs and trees, you can't do the same, but you can still examine
-them. You can just do
-
-------------------------------------------------
-$ git show <dangling-blob/tree-sha-goes-here>
-------------------------------------------------
-
-to show what the contents of the blob were (or, for a tree, basically
-what the "ls" for that directory was), and that may give you some idea
-of what the operation was that left that dangling object.
-
-Usually, dangling blobs and trees aren't very interesting. They're
-almost always the result of either being a half-way mergebase (the blob
-will often even have the conflict markers from a merge in it, if you
-have had conflicting merges that you fixed up by hand), or simply
-because you interrupted a "git fetch" with ^C or something like that,
-leaving _some_ of the new objects in the object database, but just
-dangling and useless.
+[[object-details]]
+Object storage format
+---------------------
-Anyway, once you are sure that you're not interested in any dangling
-state, you can just prune all unreachable objects:
+All objects have a statically determined "type" which identifies the
+format of the object (i.e. how it is used, and how it can refer to other
+objects). There are currently four different object types: "blob",
+"tree", "commit", and "tag".
-------------------------------------------------
-$ git prune
-------------------------------------------------
+Regardless of object type, all objects share the following
+characteristics: they are all deflated with zlib, and have a header
+that not only specifies their type, but also provides size information
+about the data in the object. It's worth noting that the SHA1 hash
+that is used to name the object is the hash of the original data
+plus this header, so `sha1sum` 'file' does not match the object name
+for 'file'.
+(Historical note: in the dawn of the age of git the hash
+was the sha1 of the 'compressed' object.)
-and they'll be gone. But you should only run "git prune" on a quiescent
-repository - it's kind of like doing a filesystem fsck recovery: you
-don't want to do that while the filesystem is mounted.
+As a result, the general consistency of an object can always be tested
+independently of the contents or the type of the object: all objects can
+be validated by verifying that (a) their hashes match the content of the
+file and (b) the object successfully inflates to a stream of bytes that
+forms a sequence of <ascii type without space> {plus} <space> {plus} <ascii decimal
+size> {plus} <byte\0> {plus} <binary object data>.
-(The same is true of "git-fsck" itself, btw - but since
-git-fsck never actually *changes* the repository, it just reports
-on what it found, git-fsck itself is never "dangerous" to run.
-Running it while somebody is actually changing the repository can cause
-confusing and scary messages, but it won't actually do anything bad. In
-contrast, running "git prune" while somebody is actively changing the
-repository is a *BAD* idea).
+The structured objects can further have their structure and
+connectivity to other objects verified. This is generally done with
+the `git-fsck` program, which generates a full dependency graph
+of all objects, and verifies their internal consistency (in addition
+to just verifying their superficial consistency through the hash).
[[birdview-on-the-source-code]]
A birds-eye view of Git's source code
- `get_sha1()` returns 0 on _success_. This might surprise some new
Git hackers, but there is a long tradition in UNIX to return different
- negative numbers in case of different errors -- and 0 on success.
+ negative numbers in case of different errors--and 0 on success.
- the variable `sha1` in the function signature of `get_sha1()` is `unsigned
char \*`, but is actually expected to be a pointer to `unsigned
$ git branch -d new # delete branch "new"
-----------------------------------------------
-Instead of basing new branch on current HEAD (the default), use:
+Instead of basing a new branch on current HEAD (the default), use:
-----------------------------------------------
$ git branch new test # branch named "test"
This is a work in progress.
The basic requirements:
- - It must be readable in order, from beginning to end, by
- someone intelligent with a basic grasp of the UNIX
- command line, but without any special knowledge of git. If
- necessary, any other prerequisites should be specifically
- mentioned as they arise.
- - Whenever possible, section headings should clearly describe
- the task they explain how to do, in language that requires
- no more knowledge than necessary: for example, "importing
- patches into a project" rather than "the git-am command"
+
+- It must be readable in order, from beginning to end, by someone
+ intelligent with a basic grasp of the UNIX command line, but without
+ any special knowledge of git. If necessary, any other prerequisites
+ should be specifically mentioned as they arise.
+- Whenever possible, section headings should clearly describe the task
+ they explain how to do, in language that requires no more knowledge
+ than necessary: for example, "importing patches into a project" rather
+ than "the git-am command"
Think about how to create a clear chapter dependency graph that will
allow people to get to important topics without necessarily reading
everything in between.
Scan Documentation/ for other stuff left out; in particular:
- howto's
- some of technical/?
- hooks
- list of commands in gitlink:git[1]
+
+- howto's
+- some of technical/?
+- hooks
+- list of commands in linkgit:git[1]
Scan email archives for other stuff left out
Alternates, clone -reference, etc.
-git unpack-objects -r for recovery
+More on recovery from repository corruption. See:
+ http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
+ http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
+ http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2