importantly, it is a globally unique name for this commit: so if you
tell somebody else the object name (for example in email), then you are
guaranteed that name will refer to the same commit in their repository
-that you it does in yours (assuming their repository has that commit at
+that it does in yours (assuming their repository has that commit at
all).
Understanding history: commits, parents, and reachability
that Y is a descendent of X, or that there is a chain of parents
leading from commit Y to commit X.
-Undestanding history: History diagrams
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Understanding history: History diagrams
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We will sometimes represent git history using diagrams like the one
below. Commits are shown as "o", and the links between them with
Git provides extremely flexible and fast tools for exploring the
history of a project.
-We start with one specialized tool which is useful for finding the
+We start with one specialized tool that is useful for finding the
commit that introduced a bug into a project.
How to use bisect to find a regression
We have seen several ways of naming commits already:
- - 40-hexdigit SHA1 id
+ - 40-hexdigit object name
- branch name: refers to the commit at the head of the given
branch
- tag name: refers to the commit pointed to by the given tag
name revisions. Some examples:
-------------------------------------------------
-$ git show fb47ddb2 # the first few characters of the SHA1 id
+$ git show fb47ddb2 # the first few characters of the object name
# are usually enough to specify it uniquely
$ git show HEAD^ # the parent of the HEAD commit
$ git show HEAD^^ # the grandparent
branch.
The gitlink:git-rev-parse[1] command is a low-level command that is
-occasionally useful for translating some name for a commit to the SHA1 id for
-that commit:
+occasionally useful for translating some name for a commit to the object
+name for that commit:
-------------------------------------------------
$ git rev-parse origin
Note that git log starts with the most recent commit and works
backwards through the parents; however, since git history can contain
-multiple independant lines of development, the particular order that
+multiple independent lines of development, the particular order that
commits are listed in may be somewhat arbitrary.
Generating diffs
will tell you whether the contents of the project are the same at the
two branches; in theory, however, it's possible that the same project
contents could have been arrived at by two different historical
-routes. You could compare the SHA1 id's:
+routes. You could compare the object names:
-------------------------------------------------
$ git rev-list origin
Alternatively, note that
-------------------------------------------------
-$ git log v1.5.0-rc1..305db0fd
+$ git log v1.5.0-rc1..e05db0fd
-------------------------------------------------
-will produce empty output if and only if v1.5.0-rc1 includes 305db0fd,
+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
+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
+
+-------------------------------------------------
+$ git show-branch e05db0fd v1.5.0-rc0 v1.5.0-rc1 v1.5.0-rc2
+! [e05db0fd] Fix warnings in sha1_file.c - use C99 printf format if
+available
+ ! [v1.5.0-rc0] GIT v1.5.0 preview
+ ! [v1.5.0-rc1] GIT v1.5.0-rc1
+ ! [v1.5.0-rc2] GIT v1.5.0-rc2
+...
+-------------------------------------------------
+
+then search for a line that looks like
+
+-------------------------------------------------
++ ++ [e05db0fd] Fix warnings in sha1_file.c - use C99 printf format if
+available
+-------------------------------------------------
+
+Which shows that e05db0fd is reachable from itself, from v1.5.0-rc1, and
+from v1.5.0-rc2, but not from v1.5.0-rc0.
+
+
Developing with git
===================
-------------------------------------------------
and git will prompt you for a commit message and then create the new
-commmit. Check to make sure it looks like what you expected with
+commit. Check to make sure it looks like what you expected with
-------------------------------------------------
$ git show
Checking the repository for corruption
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The gitlink:git-fsck[1] command runs a number of self-consistency
-checks on the repository, and reports on any problems. This may take some
+The gitlink: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 objects that are harmless, but also unnecessary; you can
-remove them at any time with gitlink:git-prune[1] or the --prune option to
-gitlink:git-gc[1]:
+Dangling objects are objects that are harmless, but also unnecessary;
+you can remove them at any time with gitlink:git-prune[1] or the --prune
+option to gitlink:git-gc[1]:
-------------------------------------------------
$ git gc --prune
-------------------------------------------------
-This may be time-consuming. Unlike most other git operations (including git-gc
-when run without any options), it is not safe to prune while other git
-operations are in progress in the same repository.
+This may be time-consuming. Unlike most other git operations (including
+git-gc when run without any options), it is not safe to prune while
+other git operations are in progress in the same repository.
For more about dangling objects, see <<dangling-objects>>.
Recovering lost changes
~~~~~~~~~~~~~~~~~~~~~~~
-TODO:
- reflog
- git-fsck
- low-level examination of objects
+Reflogs
+^^^^^^^
+
+Say you modify a branch with gitlink:git-reset[1] --hard, and then
+realize that the branch was the only reference you had to that point in
+history.
+
+Fortunately, git also keeps a log, called a "reflog", of all the
+previous values of each branch. So in this case you can still find the
+old history using, for example,
+
+-------------------------------------------------
+$ 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:
+
+-------------------------------------------------
+$ git show master@{2} # See where the branch pointed 2,
+$ git show master@{3} # 3, ... changes ago.
+$ gitk master@{yesterday} # See where it pointed yesterday,
+$ gitk master@{"1 week ago"} # ... or last week
+-------------------------------------------------
+
+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
+how to control this pruning, and see the "SPECIFYING REVISIONS"
+section of gitlink: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
+same project, the reflog history is not shared: it tells you only about
+how the branches in your local repository have changed over time.
+
+Examining dangling objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In some situations the reflog may not be able to save you. For
+example, suppose you delete a branch, then realize you need the history
+it pointed you. The reflog is also deleted; however, if you have not
+yet pruned the repository, then you may still be able to find
+the lost commits; run git-fsck and watch for output that mentions
+"dangling commits":
+
+-------------------------------------------------
+$ git fsck
+dangling commit 7281251ddd2a61e38657c827739c57015671a6b3
+dangling commit 2706a059f258c6b245f298dc4ff2ccd30ec21a63
+dangling commit 13472b7c4b80851a1bc551779171dcb03655e9b5
+...
+-------------------------------------------------
+
+You can examine
+one of those dangling commits with, for example,
+
+------------------------------------------------
+$ gitk 7281251ddd --not --all
+------------------------------------------------
+
+which does what it sounds like: it says that you want to see the commit
+history that is described by the dangling commit(s), but not the
+history that is described by all your existing branches and tags. Thus
+you get exactly the history reachable from that commit that is lost.
+(And notice that it might not be just one commit: we only report the
+"tip of the line" as being dangling, but there might be a whole deep
+and complex commit history that was gotten dropped.)
+
+If you decide you want the history back, you can always create a new
+reference pointing to it, for example, a new branch:
+
+------------------------------------------------
+$ git branch recovered-branch 7281251ddd
+------------------------------------------------
+
Sharing development with others
===============================
<<fast-forwards,fast forward>>; instead, your branch will just be
updated to point to the latest commit from the upstream branch).
-The git-pull command can also be given "." as the "remote" repository, in
-which case it just merges in a branch from the current repository; so
+The git-pull command can also be given "." as the "remote" repository,
+in which case it just merges in a branch from the current repository; so
the commands
-------------------------------------------------
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-patches[1]; for example:
+First, use gitlink:git-format-patch[1]; for example:
-------------------------------------------------
$ git format-patch origin
Allow web browsing of a repository
----------------------------------
-TODO: Brief setup-instructions for gitweb
+The gitweb cgi script provides users an easy way to browse your
+project's files and history without having to install git; see the file
+gitweb/README in the git source tree for instructions on setting it up.
Examples
--------
TODO: topic branches, typical roles as in everyday.txt, ?
-Working with other version control systems
-==========================================
-
-TODO: CVS, Subversion, series-of-release-tarballs, etc.
-
[[cleaning-up-history]]
Rewriting history and maintaining patch series
==============================================
since the tree object information is always the first line in a commit
object.
-Once you know the three trees you are going to merge (the one
-"original" tree, aka the common case, 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
+Once you know the three trees you are going to merge (the one "original"
+tree, aka the common case, 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
-always do a merge against your last commit (which should thus match
-what you have in your current index anyway).
+always do a merge against your last commit (which should thus match what
+you have in your current index anyway).
To do the merge, do
$ git-merge-index git-merge-one-file hello.c
-------------------------------------------------
-and that is what higher level `git resolve` is implemented with.
+and that is what higher level `git merge -s resolve` is implemented with.
How git stores objects efficiently: pack files
----------------------------------------------
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 obviously everything it pointed to. The branch pointer
-itself just doesn't, since you replaced it with another one.
-
-There are also other situations too 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, the most useful thing to do with dangling objects tends to be
-to do a simple
+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 obviously everything it pointed to. The
+branch pointer itself just doesn't, since you replaced it with another
+one.
+
+There are also other situations too 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, the most useful thing to do with dangling objects tends to
+be to do a simple
------------------------------------------------
$ gitk <dangling-commit-sha-goes-here> --not --all
------------------------------------------------
-which means exactly what it sounds like: it says that you want to see the
-commit history that is described by the dangling commit(s), but you do NOT
-want to see the history that is described by all your branches and tags
-(which are the things you normally reach). That basically shows you in a
-nice way what the dangling commit was (and notice that it might not be
-just one commit: we only report the "tip of the line" as being dangling,
-but there might be a whole deep and complex commit history that has gotten
-dropped - rebasing will do that).
-
-For blobs and trees, you can't do the same, but you can examine them. You
-can just do
+For blobs and trees, you can't do the same, but you can 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.
+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.
+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.
Anyway, once you are sure that you're not interested in any dangling
state, you can just prune all unreachable objects:
$ 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.
+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
allow people to get to important topics without necessarily reading
everything in between.
+Say something about .gitignore.
+
Scan Documentation/ for other stuff left out; in particular:
howto's
- README
some of technical/?
hooks
- etc.
+ list of commands in gitlink:git[1]
Scan email archives for other stuff left out
Include cross-references to the glossary, where appropriate.
-To document:
- reflogs, git reflog expire
- shallow clones?? See draft 1.5.0 release notes for some documentation.
+Document shallow clones? See draft 1.5.0 release notes for some
+documentation.
+
+Add a section on working with other version control systems, including
+CVS, Subversion, and just imports of series of release tarballs.
+
+More details on gitweb?
+
+Write a chapter on using plumbing and writing scripts.