Documentaion updates.

Mostly making the formatted html prettier.

Signed-off-by: Junio C Hamano <junkio@cox.net>
(cherry picked from 7adf1f15ebe074d4767df941817a6cf86d8e2533 commit)
This commit is contained in:
Junio C Hamano 2005-08-30 13:51:01 -07:00
parent cc9f24d024
commit 8db9307c9c
9 changed files with 501 additions and 350 deletions

View file

@ -2,10 +2,12 @@ MAN1_TXT=$(wildcard git-*.txt) gitk.txt
MAN7_TXT=git.txt MAN7_TXT=git.txt
DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT))
DOC_HTML += glossary.html
DOC_HTML += tutorial.html ARTICLES = tutorial cvs-migration diffcore howto-index
DOC_HTML += howto-index.html # with their own formatting rules.
DOC_HTML += howto/revert-branch-rebase.html SP_ARTICLES = glossary howto/revert-branch-rebase
DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
@ -58,21 +60,20 @@ clean:
%.xml : %.txt %.xml : %.txt
asciidoc -b docbook -d manpage $< asciidoc -b docbook -d manpage $<
git.html: git.txt ../README
glossary.html : glossary.txt sort_glossary.pl glossary.html : glossary.txt sort_glossary.pl
cat $< | \ cat $< | \
perl sort_glossary.pl | \ perl sort_glossary.pl | \
asciidoc -b xhtml11 - > glossary.html asciidoc -b xhtml11 - > glossary.html
tutorial.html : tutorial.txt
asciidoc -b xhtml11 tutorial.txt
howto-index.txt: howto-index.sh $(wildcard howto/*.txt) howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
rm -f $@+ $@ rm -f $@+ $@
sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
mv $@+ $@ mv $@+ $@
howto-index.html: howto-index.txt $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
asciidoc -b xhtml11 howto-index.txt asciidoc -b xhtml11 $*.txt
WEBDOC_DEST = /pub/software/scm/git/docs WEBDOC_DEST = /pub/software/scm/git/docs

View file

@ -1,5 +1,6 @@
Git for CVS users Git for CVS users
================= =================
v0.99.5, Aug 2005
Ok, so you're a CVS user. That's ok, it's a treatable condition, and the Ok, so you're a CVS user. That's ok, it's a treatable condition, and the
first step to recovery is admitting you have a problem. The fact that first step to recovery is admitting you have a problem. The fact that
@ -8,12 +9,12 @@ already.
The thing about CVS is that it absolutely sucks as a source control The thing about CVS is that it absolutely sucks as a source control
manager, and you'll thus be happy with almost anything else. Git, manager, and you'll thus be happy with almost anything else. Git,
however, may be a bit _too_ different (read: "good") for your taste, and however, may be a bit 'too' different (read: "good") for your taste, and
does a lot of things differently. does a lot of things differently.
One particular suckage of CVS is very hard to work around: CVS is One particular suckage of CVS is very hard to work around: CVS is
basically a tool for tracking _file_ history, while git is a tool for basically a tool for tracking 'file' history, while git is a tool for
tracking _project_ history. This sometimes causes problems if you are tracking 'project' history. This sometimes causes problems if you are
used to doing very strange things in CVS, in particular if you're doing used to doing very strange things in CVS, in particular if you're doing
things like making branches of just a subset of the project. Git can't things like making branches of just a subset of the project. Git can't
track that, since git never tracks things on the level of an individual track that, since git never tracks things on the level of an individual
@ -22,17 +23,18 @@ file, only on the whole project level.
The good news is that most people don't do that, and in fact most sane The good news is that most people don't do that, and in fact most sane
people think it's a bug in CVS that makes it tag (and check in changes) people think it's a bug in CVS that makes it tag (and check in changes)
one file at a time. So most projects you'll ever see will use CVS one file at a time. So most projects you'll ever see will use CVS
_as_if_ it was sane. In which case you'll find it very easy indeed to 'as if' it was sane. In which case you'll find it very easy indeed to
move over to Git. move over to Git.
First off: this is not a git tutorial. See Documentation/tutorial.txt First off: this is not a git tutorial. See
for how git actually works. This is more of a random collection of link:tutorial.html[Documentation/tutorial.txt] for how git
gotcha's and notes on converting from CVS to git. actually works. This is more of a random collection of gotcha's
and notes on converting from CVS to git.
Second: CVS has the notion of a "repository" as opposed to the thing Second: CVS has the notion of a "repository" as opposed to the thing
that you're actually working in (your working directory, or your that you're actually working in (your working directory, or your
"checked out tree"). Git does not have that notion at all, and all git "checked out tree"). Git does not have that notion at all, and all git
working directories _are_ the repositories. However, you can easily working directories 'are' the repositories. However, you can easily
emulate the CVS model by having one special "global repository", which emulate the CVS model by having one special "global repository", which
people can synchronize with. See details later, but in the meantime people can synchronize with. See details later, but in the meantime
just keep in mind that with git, every checked out working tree will just keep in mind that with git, every checked out working tree will
@ -55,7 +57,7 @@ will need the help of a program called "cvsps":
which is not actually related to git at all, but which makes CVS usage which is not actually related to git at all, but which makes CVS usage
look almost sane (ie you almost certainly want to have it even if you look almost sane (ie you almost certainly want to have it even if you
decide to stay with CVS). However, git will want at _least_ version 2.1 decide to stay with CVS). However, git will want 'at least' version 2.1
of cvsps (available at the address above), and in fact will currently of cvsps (available at the address above), and in fact will currently
refuse to work with anything else. refuse to work with anything else.

View file

@ -1,5 +1,5 @@
The output format from "git-diff-cache", "git-diff-tree" and The output format from "git-diff-cache", "git-diff-tree" and
"git-diff-files" is very similar. "git-diff-files" are very similar.
These commands all compare two sets of things; what are These commands all compare two sets of things; what are
compared are different: compared are different:
@ -19,35 +19,41 @@ git-diff-files [<pattern>...]::
An output line is formatted this way: An output line is formatted this way:
------------------------------------------------
in-place edit :100644 100644 bcd1234... 0123456... M file0 in-place edit :100644 100644 bcd1234... 0123456... M file0
copy-edit :100644 100644 abcd123... 1234567... C68 file1 file2 copy-edit :100644 100644 abcd123... 1234567... C68 file1 file2
rename-edit :100644 100644 abcd123... 1234567... R86 file1 file3 rename-edit :100644 100644 abcd123... 1234567... R86 file1 file3
create :000000 100644 0000000... 1234567... N file4 create :000000 100644 0000000... 1234567... A file4
delete :100644 000000 1234567... 0000000... D file5 delete :100644 000000 1234567... 0000000... D file5
unmerged :000000 000000 0000000... 0000000... U file6 unmerged :000000 000000 0000000... 0000000... U file6
------------------------------------------------
That is, from the left to the right: That is, from the left to the right:
(1) a colon. . a colon.
(2) mode for "src"; 000000 if creation or unmerged. . mode for "src"; 000000 if creation or unmerged.
(3) a space. . a space.
(4) mode for "dst"; 000000 if deletion or unmerged. . mode for "dst"; 000000 if deletion or unmerged.
(5) a space. . a space.
(6) sha1 for "src"; 0{40} if creation or unmerged. . sha1 for "src"; 0\{40\} if creation or unmerged.
(7) a space. . a space.
(8) sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree". . sha1 for "dst"; 0\{40\} if creation, unmerged or "look at work tree".
(9) a space. . a space.
(10) status, followed by optional "score" number. . status, followed by optional "score" number.
(11) a tab or a NUL when '-z' option is used. . a tab or a NUL when '-z' option is used.
(12) path for "src" . path for "src"
(13) a tab or a NUL when '-z' option is used; only exists for C or R. . a tab or a NUL when '-z' option is used; only exists for C or R.
(14) path for "dst"; only exists for C or R. . path for "dst"; only exists for C or R.
(15) an LF or a NUL when '-z' option is used, to terminate the record. . an LF or a NUL when '-z' option is used, to terminate the record.
<sha1> is shown as all 0's if new is a file on the filesystem <sha1> is shown as all 0's if new is a file on the filesystem
and it is out of sync with the cache. Example: and it is out of sync with the cache.
:100644 100644 5be4a4...... 000000...... M file.c Example:
------------------------------------------------
:100644 100644 5be4a4...... 000000...... M file.c
------------------------------------------------
Generating patches with -p Generating patches with -p
-------------------------- --------------------------
@ -107,20 +113,20 @@ Git specific extension to diff format
What -p option produces is slightly different from the What -p option produces is slightly different from the
traditional diff format. traditional diff format.
(1) It is preceeded with a "git diff" header, that looks like 1. It is preceeded with a "git diff" header, that looks like
this: this:
diff --git a/file1 b/file2 diff --git a/file1 b/file2
+
The `a/` and `b/` filenames are the same unless rename/copy is
involved. Especially, even for a creation or a deletion,
`/dev/null` is _not_ used in place of `a/` or `b/` filenames.
+
When rename/copy is involved, `file1` and `file2` shows the
name of the source file of the rename/copy and the name of
the file that rename/copy produces, respectively.
The a/ and b/ filenames are the same unless rename/copy is 2. It is followed by extended header lines that are one or
involved. Especially, even for a creation or a deletion,
/dev/null is _not_ used in place of a/ or b/ filename.
When rename/copy is involved, file1 and file2 shows the
name of the source file of the rename/copy and the name of
the file that rename/copy produces, respectively.
(2) It is followed by extended header lines that are one or
more of: more of:
old mode <mode> old mode <mode>

View file

@ -51,3 +51,5 @@
Swap two inputs; that is, show differences from cache or Swap two inputs; that is, show differences from cache or
on-disk file to tree contents. on-disk file to tree contents.
For more detailed explanation on these common options, see also
link:diffcore.html[diffcore documentation].

View file

@ -22,8 +22,8 @@ The git-diff-* family works by first comparing two sets of
files: files:
- git-diff-cache compares contents of a "tree" object and the - git-diff-cache compares contents of a "tree" object and the
working directory (when --cached flag is not used) or a working directory (when '--cached' flag is not used) or a
"tree" object and the index file (when --cached flag is "tree" object and the index file (when '--cached' flag is
used); used);
- git-diff-files compares contents of the index file and the - git-diff-files compares contents of the index file and the
@ -37,29 +37,31 @@ comparison is passed from these commands to what is internally
called "diffcore", in a format similar to what is output when called "diffcore", in a format similar to what is output when
the -p option is not used. E.g. the -p option is not used. E.g.
in-place edit :100644 100644 bcd1234... 0123456... M file0 ------------------------------------------------
create :000000 100644 0000000... 1234567... N file4 in-place edit :100644 100644 bcd1234... 0123456... M file0
delete :100644 000000 1234567... 0000000... D file5 create :000000 100644 0000000... 1234567... A file4
unmerged :000000 000000 0000000... 0000000... U file6 delete :100644 000000 1234567... 0000000... D file5
unmerged :000000 000000 0000000... 0000000... U file6
------------------------------------------------
The diffcore mechanism is fed a list of such comparison results The diffcore mechanism is fed a list of such comparison results
(each of which is called "filepair", although at this point each (each of which is called "filepair", although at this point each
of them talks about a single file), and transforms such a list of them talks about a single file), and transforms such a list
into another list. There are currently 6 such transformations: into another list. There are currently 6 such transformations:
- diffcore-pathspec - diffcore-pathspec
- diffcore-break - diffcore-break
- diffcore-rename - diffcore-rename
- diffcore-merge-broken - diffcore-merge-broken
- diffcore-pickaxe - diffcore-pickaxe
- diffcore-order - diffcore-order
These are applied in sequence. The set of filepairs git-diff-* These are applied in sequence. The set of filepairs git-diff-\*
commands find are used as the input to diffcore-pathspec, and commands find are used as the input to diffcore-pathspec, and
the output from diffcore-pathspec is used as the input to the the output from diffcore-pathspec is used as the input to the
next transformation. The final result is then passed to the next transformation. The final result is then passed to the
output routine and generates either diff-raw format (see Output output routine and generates either diff-raw format (see Output
format sections of the manual for git-diff-* commands) or format sections of the manual for git-diff-\* commands) or
diff-patch format. diff-patch format.
@ -87,13 +89,17 @@ used to detect a filepair that represents "complete rewrite" and
break such filepair into two filepairs that represent delete and break such filepair into two filepairs that represent delete and
create. E.g. If the input contained this filepair: create. E.g. If the input contained this filepair:
:100644 100644 bcd1234... 0123456... M file0 ------------------------------------------------
:100644 100644 bcd1234... 0123456... M file0
------------------------------------------------
and if it detects that the file "file0" is completely rewritten, and if it detects that the file "file0" is completely rewritten,
it changes it to: it changes it to:
:100644 000000 bcd1234... 0000000... D file0 ------------------------------------------------
:000000 100644 0000000... 0123456... N file0 :100644 000000 bcd1234... 0000000... D file0
:000000 100644 0000000... 0123456... A file0
------------------------------------------------
For the purpose of breaking a filepair, diffcore-break examines For the purpose of breaking a filepair, diffcore-break examines
the extent of changes between the contents of the files before the extent of changes between the contents of the files before
@ -117,14 +123,18 @@ controlled by the -M option (to detect renames) and the -C option
(to detect copies as well) to the git-diff-* commands. If the (to detect copies as well) to the git-diff-* commands. If the
input contained these filepairs: input contained these filepairs:
:100644 000000 0123456... 0000000... D fileX ------------------------------------------------
:000000 100644 0000000... 0123456... N file0 :100644 000000 0123456... 0000000... D fileX
:000000 100644 0000000... 0123456... A file0
------------------------------------------------
and the contents of the deleted file fileX is similar enough to and the contents of the deleted file fileX is similar enough to
the contents of the created file file0, then rename detection the contents of the created file file0, then rename detection
merges these filepairs and creates: merges these filepairs and creates:
:100644 100644 0123456... 0123456... R100 fileX file0 ------------------------------------------------
:100644 100644 0123456... 0123456... R100 fileX file0
------------------------------------------------
When the "-C" option is used, the original contents of modified When the "-C" option is used, the original contents of modified
files and contents of unchanged files are considered as files and contents of unchanged files are considered as
@ -133,15 +143,19 @@ addition to the deleted files. If the input were like these
filepairs, that talk about a modified file fileY and a newly filepairs, that talk about a modified file fileY and a newly
created file file0: created file file0:
:100644 100644 0123456... 1234567... M fileY ------------------------------------------------
:000000 100644 0000000... 0123456... N file0 :100644 100644 0123456... 1234567... M fileY
:000000 100644 0000000... 0123456... A file0
------------------------------------------------
the original contents of fileY and the resulting contents of the original contents of fileY and the resulting contents of
file0 are compared, and if they are similar enough, they are file0 are compared, and if they are similar enough, they are
changed to: changed to:
:100644 100644 0123456... 1234567... M fileY ------------------------------------------------
:100644 100644 0123456... 0123456... C100 fileY file0 :100644 100644 0123456... 1234567... M fileY
:100644 100644 0123456... 0123456... C100 fileY file0
------------------------------------------------
In both rename and copy detection, the same "extent of changes" In both rename and copy detection, the same "extent of changes"
algorithm used in diffcore-break is used to determine if two algorithm used in diffcore-break is used to determine if two
@ -151,11 +165,11 @@ number after "-M" or "-C" option (e.g. "-M8" to tell it to use
8/10 = 80%). 8/10 = 80%).
Note. When the "-C" option is used with --find-copies-harder Note. When the "-C" option is used with --find-copies-harder
option, git-diff-* commands feed unmodified filepairs to option, git-diff-\* commands feed unmodified filepairs to
diffcore mechanism as well as modified ones. This lets the copy diffcore mechanism as well as modified ones. This lets the copy
detector consider unmodified files as copy source candidates at detector consider unmodified files as copy source candidates at
the expense of making it slower. Without --find-copies-harder, the expense of making it slower. Without --find-copies-harder,
git-diff-* commands can detect copies only if the file that was git-diff-\* commands can detect copies only if the file that was
copied happened to have been modified in the same changeset. copied happened to have been modified in the same changeset.
@ -186,10 +200,10 @@ material is deleted, the broken pairs are merged back into a
single modification) by giving a second number to -B option, single modification) by giving a second number to -B option,
like these: like these:
-B50/60 (give 50% "break score" to diffcore-break, use * -B50/60 (give 50% "break score" to diffcore-break, use 60%
60% for diffcore-merge-broken). for diffcore-merge-broken).
-B/60 (the same as above, since diffcore-break defautls to
50%). * -B/60 (the same as above, since diffcore-break defaults to 50%).
Note that earlier implementation left a broken pair as a separate Note that earlier implementation left a broken pair as a separate
creation and deletion patches. This was unnecessary hack and creation and deletion patches. This was unnecessary hack and
@ -237,12 +251,14 @@ in the file are output before ones that match a later line, and
filepairs that do not match any glob pattern are output last. filepairs that do not match any glob pattern are output last.
As an example, typical orderfile for the core GIT probably As an example, typical orderfile for the core GIT probably
should look like this: would look like this:
------------------------------------------------
README README
Makefile Makefile
Documentation Documentation
*.h *.h
*.c *.c
t t
------------------------------------------------

View file

@ -12,6 +12,8 @@ SYNOPSIS
'git bisect' bad <rev> 'git bisect' bad <rev>
'git bisect' good <rev> 'git bisect' good <rev>
'git bisect' reset [<branch>] 'git bisect' reset [<branch>]
'git bisect' visualize
DESCRIPTION DESCRIPTION
----------- -----------
@ -67,6 +69,12 @@ branches ("git bisect start" will do that for you too, actually: it will
reset the bisection state, and before it does that it checks that you're reset the bisection state, and before it does that it checks that you're
not using some old bisection branch). not using some old bisection branch).
During the bisection process, you can say
git bisect visualize
to see the currently remaining suspects in `gitk`.
Author Author
------ ------

View file

@ -19,11 +19,14 @@ This is reference information for the core git commands.
Before reading this cover to cover, you may want to take a look Before reading this cover to cover, you may want to take a look
at the link:tutorial.html[tutorial] document. at the link:tutorial.html[tutorial] document.
The Discussion section below contains much useful definition and The <<Discussion>> section below contains much useful definition and
clarification info - read that first. And of the commands, I suggest clarification info - read that first. And of the commands, I suggest
reading link:git-update-cache.html[git-update-cache] and reading link:git-update-cache.html[git-update-cache] and
link:git-read-tree.html[git-read-tree] first - I wish I had! link:git-read-tree.html[git-read-tree] first - I wish I had!
If you are migrating from CVS, link:cvs-migration.html[cvs migration]
document may be helpful after you finish the tutorial.
After you get the general feel from the tutorial and this After you get the general feel from the tutorial and this
overview page, you may want to take a look at the overview page, you may want to take a look at the
link:howto-index.html[howto] documents. link:howto-index.html[howto] documents.
@ -483,8 +486,8 @@ git Diffs
link:git-diff-files.html[git-diff-files]; link:git-diff-files.html[git-diff-files];
link:git-diff-tree.html[git-diff-tree] link:git-diff-tree.html[git-diff-tree]
Discussion Discussion[[Discussion]]
---------- ------------------------
include::../README[] include::../README[]
Author Author

View file

@ -32,13 +32,15 @@ one for a totally new project, or an existing working tree that you want
to import into git. to import into git.
For our first example, we're going to start a totally new repository from For our first example, we're going to start a totally new repository from
scratch, with no pre-existing files, and we'll call it "git-tutorial". scratch, with no pre-existing files, and we'll call it `git-tutorial`.
To start up, create a subdirectory for it, change into that To start up, create a subdirectory for it, change into that
subdirectory, and initialize the git infrastructure with "git-init-db": subdirectory, and initialize the git infrastructure with `git-init-db`:
mkdir git-tutorial ------------------------------------------------
cd git-tutorial mkdir git-tutorial
git-init-db cd git-tutorial
git-init-db
------------------------------------------------
to which git will reply to which git will reply
@ -46,48 +48,50 @@ to which git will reply
which is just git's way of saying that you haven't been doing anything which is just git's way of saying that you haven't been doing anything
strange, and that it will have created a local .git directory setup for strange, and that it will have created a local .git directory setup for
your new project. You will now have a ".git" directory, and you can your new project. You will now have a `.git` directory, and you can
inspect that with "ls". For your new empty project, ls should show you inspect that with `ls`. For your new empty project, it should show you
three entries, among other things: three entries, among other things:
- a symlink called HEAD, pointing to "refs/heads/master" - a symlink called `HEAD`, pointing to `refs/heads/master`
+
Don't worry about the fact that the file that the `HEAD` link points to
doesn't even exist yet - you haven't created the commit that will
start your `HEAD` development branch yet.
Don't worry about the fact that the file that the HEAD link points to - a subdirectory called `objects`, which will contain all the
doesn't even exist yet - you haven't created the commit that will
start your HEAD development branch yet.
- a subdirectory called "objects", which will contain all the
objects of your project. You should never have any real reason to objects of your project. You should never have any real reason to
look at the objects directly, but you might want to know that these look at the objects directly, but you might want to know that these
objects are what contains all the real _data_ in your repository. objects are what contains all the real 'data' in your repository.
- a subdirectory called "refs", which contains references to objects. - a subdirectory called `refs`, which contains references to objects.
In particular, the "refs" subdirectory will contain two other In particular, the `refs` subdirectory will contain two other
subdirectories, named "heads" and "tags" respectively. They do subdirectories, named `heads` and `tags` respectively. They do
exactly what their names imply: they contain references to any number exactly what their names imply: they contain references to any number
of different "heads" of development (aka "branches"), and to any of different 'heads' of development (aka 'branches'), and to any
"tags" that you have created to name specific versions in your 'tags' that you have created to name specific versions in your
repository. repository.
One note: the special "master" head is the default branch, which is One note: the special `master` head is the default branch, which is
why the .git/HEAD file was created as a symlink to it even if it why the `.git/HEAD` file was created as a symlink to it even if it
doesn't yet exist. Basically, the HEAD link is supposed to always doesn't yet exist. Basically, the `HEAD` link is supposed to always
point to the branch you are working on right now, and you always point to the branch you are working on right now, and you always
start out expecting to work on the "master" branch. start out expecting to work on the `master` branch.
However, this is only a convention, and you can name your branches However, this is only a convention, and you can name your branches
anything you want, and don't have to ever even _have_ a "master" anything you want, and don't have to ever even 'have' a `master`
branch. A number of the git tools will assume that .git/HEAD is branch. A number of the git tools will assume that `.git/HEAD` is
valid, though. valid, though.
[ Implementation note: an "object" is identified by its 160-bit SHA1 [NOTE]
hash, aka "name", and a reference to an object is always the 40-byte An "object" is identified by its 160-bit SHA1 hash, aka "name",
hex representation of that SHA1 name. The files in the "refs" and a reference to an object is always the 40-byte hex
subdirectory are expected to contain these hex references (usually representation of that SHA1 name. The files in the "refs"
with a final '\n' at the end), and you should thus expect to see a subdirectory are expected to contain these hex references
number of 41-byte files containing these references in this refs (usually with a final '\n' at the end), and you should thus
subdirectories when you actually start populating your tree ] expect to see a number of 41-byte files containing these
references in this refs subdirectories when you actually start
populating your tree.
You have now created your first git repository. Of course, since it's You have now created your first git repository. Of course, since it's
empty, that's not very useful, so let's start populating it with data. empty, that's not very useful, so let's start populating it with data.
@ -103,8 +107,10 @@ Start off with just creating any random files that you want to maintain
in your git repository. We'll start off with a few bad examples, just to in your git repository. We'll start off with a few bad examples, just to
get a feel for how this works: get a feel for how this works:
echo "Hello World" >hello ------------------------------------------------
echo "Silly example" >example echo "Hello World" >hello
echo "Silly example" >example
------------------------------------------------
you have now created two files in your working tree (aka "working directory"), but to you have now created two files in your working tree (aka "working directory"), but to
actually check in your hard work, you will have to go through two steps: actually check in your hard work, you will have to go through two steps:
@ -115,16 +121,18 @@ actually check in your hard work, you will have to go through two steps:
- commit that index file as an object. - commit that index file as an object.
The first step is trivial: when you want to tell git about any changes The first step is trivial: when you want to tell git about any changes
to your working tree, you use the "git-update-cache" program. That to your working tree, you use the `git-update-cache` program. That
program normally just takes a list of filenames you want to update, but program normally just takes a list of filenames you want to update, but
to avoid trivial mistakes, it refuses to add new entries to the cache to avoid trivial mistakes, it refuses to add new entries to the cache
(or remove existing ones) unless you explicitly tell it that you're (or remove existing ones) unless you explicitly tell it that you're
adding a new entry with the "--add" flag (or removing an entry with the adding a new entry with the `--add` flag (or removing an entry with the
"--remove") flag. `--remove`) flag.
So to populate the index with the two files you just created, you can do So to populate the index with the two files you just created, you can do
git-update-cache --add hello example ------------------------------------------------
git-update-cache --add hello example
------------------------------------------------
and you have now told git to track those two files. and you have now told git to track those two files.
@ -156,23 +164,25 @@ regular file), and you can see the contents with
which will print out "Hello World". The object 557db03 is nothing which will print out "Hello World". The object 557db03 is nothing
more than the contents of your file "hello". more than the contents of your file "hello".
[ Digression: don't confuse that object with the file "hello" itself. The [NOTE]
object is literally just those specific _contents_ of the file, and Don't confuse that object with the file "hello" itself. The
however much you later change the contents in file "hello", the object we object is literally just those specific _contents_ of the file, and
just looked at will never change. Objects are immutable. ] however much you later change the contents in file "hello", the object we
just looked at will never change. Objects are immutable.
[ Digression #2: the second example demonstrates that you can [NOTE]
abbreviate the object name to only the first several The second example demonstrates that you can
hexadecimal digits in most places. ] abbreviate the object name to only the first several
hexadecimal digits in most places.
Anyway, as we mentioned previously, you normally never actually take a Anyway, as we mentioned previously, you normally never actually take a
look at the objects themselves, and typing long 40-character hex look at the objects themselves, and typing long 40-character hex
names is not something you'd normally want to do. The above digression names is not something you'd normally want to do. The above digression
was just to show that "git-update-cache" did something magical, and was just to show that `git-update-cache` did something magical, and
actually saved away the contents of your files into the git object actually saved away the contents of your files into the git object
database. database.
Updating the cache did something else too: it created a ".git/index" Updating the cache did something else too: it created a `.git/index`
file. This is the index that describes your current working tree, and file. This is the index that describes your current working tree, and
something you should be very aware of. Again, you normally never worry something you should be very aware of. Again, you normally never worry
about the index file itself, but you should be aware of the fact that about the index file itself, but you should be aware of the fact that
@ -185,7 +195,9 @@ most basic git commands to manipulate the files or look at their status.
In particular, let's not even check in the two files into git yet, we'll In particular, let's not even check in the two files into git yet, we'll
start off by adding another line to "hello" first: start off by adding another line to "hello" first:
echo "It's a new day for git" >>hello ------------------------------------------------
echo "It's a new day for git" >>hello
------------------------------------------------
and you can now, since you told git about the previous state of "hello", ask and you can now, since you told git about the previous state of "hello", ask
git what has changed in the tree compared to your old index, using the git what has changed in the tree compared to your old index, using the
@ -241,7 +253,9 @@ index. In other words, we're now tying together all the different
filenames with their contents (and their permissions), and we're filenames with their contents (and their permissions), and we're
creating the equivalent of a git "directory" object: creating the equivalent of a git "directory" object:
git-write-tree ------------------------------------------------
git-write-tree
------------------------------------------------
and this will just output the name of the resulting tree, in this case and this will just output the name of the resulting tree, in this case
(if you have done exactly as I've described) it should be (if you have done exactly as I've described) it should be
@ -272,7 +286,9 @@ supposed to contain the reference to the top-of-tree, and since that's
exactly what git-commit-tree spits out, we can do this all with a simple exactly what git-commit-tree spits out, we can do this all with a simple
shell pipeline: shell pipeline:
echo "Initial commit" | git-commit-tree $(git-write-tree) > .git/HEAD ------------------------------------------------
echo "Initial commit" | git-commit-tree $(git-write-tree) > .git/HEAD
------------------------------------------------
which will say: which will say:
@ -344,19 +360,20 @@ current working tree state entirely. Since we just wrote the index
file to HEAD, doing "git-diff-cache --cached -p HEAD" should thus return file to HEAD, doing "git-diff-cache --cached -p HEAD" should thus return
an empty set of differences, and that's exactly what it does. an empty set of differences, and that's exactly what it does.
[ Digression: "git-diff-cache" really always uses the index for its [NOTE]
comparisons, and saying that it compares a tree against the working "git-diff-cache" really always uses the index for its
tree is thus not strictly accurate. In particular, the list of comparisons, and saying that it compares a tree against the working
files to compare (the "meta-data") _always_ comes from the index file, tree is thus not strictly accurate. In particular, the list of
regardless of whether the --cached flag is used or not. The --cached files to compare (the "meta-data") _always_ comes from the index file,
flag really only determines whether the file _contents_ to be compared regardless of whether the --cached flag is used or not. The --cached
come from the working tree or not. flag really only determines whether the file _contents_ to be compared
come from the working tree or not.
This is not hard to understand, as soon as you realize that git simply +
never knows (or cares) about files that it is not told about This is not hard to understand, as soon as you realize that git simply
explicitly. Git will never go _looking_ for files to compare, it never knows (or cares) about files that it is not told about
expects you to tell it what the files are, and that's what the index explicitly. Git will never go _looking_ for files to compare, it
is there for. ] expects you to tell it what the files are, and that's what the index
is there for.
However, our next step is to commit the _change_ we did, and again, to However, our next step is to commit the _change_ we did, and again, to
understand what's going on, keep in mind the difference between "working understand what's going on, keep in mind the difference between "working
@ -365,7 +382,9 @@ in the working tree that we want to commit, and we always have to
work through the index file, so the first thing we need to do is to work through the index file, so the first thing we need to do is to
update the index cache: update the index cache:
git-update-cache hello ------------------------------------------------
git-update-cache hello
------------------------------------------------
(note how we didn't need the "--add" flag this time, since git knew (note how we didn't need the "--add" flag this time, since git knew
about the file already). about the file already).
@ -384,7 +403,9 @@ tell commit that the HEAD was the _parent_ of the new commit, and that
this wasn't an initial commit any more), but you've done that once this wasn't an initial commit any more), but you've done that once
already, so let's just use the helpful script this time: already, so let's just use the helpful script this time:
git commit ------------------------------------------------
git commit
------------------------------------------------
which starts an editor for you to write the commit message and tells you which starts an editor for you to write the commit message and tells you
a bit about what you have done. a bit about what you have done.
@ -446,23 +467,25 @@ powerful)
and you will see exactly what has changed in the repository over its and you will see exactly what has changed in the repository over its
short history. short history.
[ Side note: the "--root" flag is a flag to git-diff-tree to tell it to [NOTE]
show the initial aka "root" commit too. Normally you'd probably not The "--root" flag is a flag to git-diff-tree to tell it to
want to see the initial import diff, but since the tutorial project show the initial aka "root" commit too. Normally you'd probably not
was started from scratch and is so small, we use it to make the result want to see the initial import diff, but since the tutorial project
a bit more interesting. ] was started from scratch and is so small, we use it to make the result
a bit more interesting.
With that, you should now be having some inkling of what git does, and With that, you should now be having some inkling of what git does, and
can explore on your own. can explore on your own.
[ Side note: most likely, you are not directly using the core [NOTE]
git Plumbing commands, but using Porcelain like Cogito on top Most likely, you are not directly using the core
of it. Cogito works a bit differently and you usually do not git Plumbing commands, but using Porcelain like Cogito on top
have to run "git-update-cache" yourself for changed files (you of it. Cogito works a bit differently and you usually do not
do tell underlying git about additions and removals via have to run "git-update-cache" yourself for changed files (you
"cg-add" and "cg-rm" commands). Just before you make a commit do tell underlying git about additions and removals via
with "cg-commit", Cogito figures out which files you modified, "cg-add" and "cg-rm" commands). Just before you make a commit
and runs "git-update-cache" on them for you. ] with "cg-commit", Cogito figures out which files you modified,
and runs "git-update-cache" on them for you.
Tagging a version Tagging a version
@ -474,7 +497,9 @@ A "light" tag is technically nothing more than a branch, except we put
it in the ".git/refs/tags/" subdirectory instead of calling it a "head". it in the ".git/refs/tags/" subdirectory instead of calling it a "head".
So the simplest form of tag involves nothing more than So the simplest form of tag involves nothing more than
git tag my-first-tag ------------------------------------------------
git tag my-first-tag
------------------------------------------------
which just writes the current HEAD into the .git/refs/tags/my-first-tag which just writes the current HEAD into the .git/refs/tags/my-first-tag
file, after which point you can then use this symbolic name for that file, after which point you can then use this symbolic name for that
@ -514,12 +539,13 @@ that unlike CVS, for example, there is no separate notion of
working tree, with the local git information hidden in the ".git" working tree, with the local git information hidden in the ".git"
subdirectory. There is nothing else. What you see is what you got. subdirectory. There is nothing else. What you see is what you got.
[ Side note: you can tell git to split the git internal information from [NOTE]
the directory that it tracks, but we'll ignore that for now: it's not You can tell git to split the git internal information from
how normal projects work, and it's really only meant for special uses. the directory that it tracks, but we'll ignore that for now: it's not
So the mental model of "the git information is always tied directly to how normal projects work, and it's really only meant for special uses.
the working tree that it describes" may not be technically 100% So the mental model of "the git information is always tied directly to
accurate, but it's a good model for all normal use ] the working tree that it describes" may not be technically 100%
accurate, but it's a good model for all normal use.
This has two implications: This has two implications:
@ -527,24 +553,24 @@ This has two implications:
made a mistake and want to start all over), you can just do simple made a mistake and want to start all over), you can just do simple
rm -rf git-tutorial rm -rf git-tutorial
+
and it will be gone. There's no external repository, and there's no and it will be gone. There's no external repository, and there's no
history outside the project you created. history outside the project you created.
- if you want to move or duplicate a git repository, you can do so. There - if you want to move or duplicate a git repository, you can do so. There
is "git clone" command, but if all you want to do is just to is "git clone" command, but if all you want to do is just to
create a copy of your repository (with all the full history that create a copy of your repository (with all the full history that
went along with it), you can do so with a regular went along with it), you can do so with a regular
"cp -a git-tutorial new-git-tutorial". "cp -a git-tutorial new-git-tutorial".
+
Note that when you've moved or copied a git repository, your git index Note that when you've moved or copied a git repository, your git index
file (which caches various information, notably some of the "stat" file (which caches various information, notably some of the "stat"
information for the files involved) will likely need to be refreshed. information for the files involved) will likely need to be refreshed.
So after you do a "cp -a" to create a new copy, you'll want to do So after you do a "cp -a" to create a new copy, you'll want to do
git-update-cache --refresh git-update-cache --refresh
+
in the new repository to make sure that the index file is up-to-date. in the new repository to make sure that the index file is up-to-date.
Note that the second point is true even across machines. You can Note that the second point is true even across machines. You can
duplicate a remote git repository with _any_ regular copy mechanism, be it duplicate a remote git repository with _any_ regular copy mechanism, be it
@ -572,15 +598,15 @@ The above can also be written as simply
and in fact a lot of the common git command combinations can be scripted and in fact a lot of the common git command combinations can be scripted
with the "git xyz" interfaces, and you can learn things by just looking with the "git xyz" interfaces, and you can learn things by just looking
at what the git-*-script scripts do ("git reset" is the above two lines at what the `git-*-script` scripts do (`git reset` is the above two lines
implemented in "git-reset-script", but some things like "git status" and implemented in `git-reset-script`, but some things like "git status" and
"git commit" are slightly more complex scripts around the basic git `git commit` are slightly more complex scripts around the basic git
commands). commands).
Many (most?) public remote repositories will not contain any of Many (most?) public remote repositories will not contain any of
the checked out files or even an index file, and will _only_ contain the the checked out files or even an index file, and will 'only' contain the
actual core git files. Such a repository usually doesn't even have the actual core git files. Such a repository usually doesn't even have the
".git" subdirectory, but has all the git files directly in the `.git` subdirectory, but has all the git files directly in the
repository. repository.
To create your own local live copy of such a "raw" git repository, you'd To create your own local live copy of such a "raw" git repository, you'd
@ -641,20 +667,25 @@ To show that as an example, let's go back to the git-tutorial repository we
used earlier, and create a branch in it. You do that by simply just used earlier, and create a branch in it. You do that by simply just
saying that you want to check out a new branch: saying that you want to check out a new branch:
git checkout -b mybranch ------------
git checkout -b mybranch
------------
will create a new branch based at the current HEAD position, and switch will create a new branch based at the current HEAD position, and switch
to it. to it.
[ Side note: if you make the decision to start your new branch at some [NOTE]
other point in the history than the current HEAD, you can do so by ================================================
just telling "git checkout" what the base of the checkout would be. If you make the decision to start your new branch at some
In other words, if you have an earlier tag or branch, you'd just do other point in the history than the current HEAD, you can do so by
just telling "git checkout" what the base of the checkout would be.
In other words, if you have an earlier tag or branch, you'd just do
git checkout -b mybranch earlier-commit git checkout -b mybranch earlier-commit
and it would create the new branch "mybranch" at the earlier commit, and it would create the new branch "mybranch" at the earlier commit,
and check out the state at that time. ] and check out the state at that time.
================================================
You can always just jump back to your original "master" branch by doing You can always just jump back to your original "master" branch by doing
@ -670,7 +701,7 @@ you have, you can say
git branch git branch
which is nothing more than a simple script around "ls .git/refs/heads". which is nothing more than a simple script around `ls .git/refs/heads`.
There will be asterisk in front of the branch you are currently on. There will be asterisk in front of the branch you are currently on.
Sometimes you may wish to create a new branch _without_ actually Sometimes you may wish to create a new branch _without_ actually
@ -693,9 +724,11 @@ branch. So assuming you created the above "mybranch" that started out
being the same as the original "master" branch, let's make sure we're in being the same as the original "master" branch, let's make sure we're in
that branch, and do some work there. that branch, and do some work there.
git checkout mybranch ------------
echo "Work, work, work" >>hello git checkout mybranch
git commit -m 'Some work.' hello echo "Work, work, work" >>hello
git commit -m 'Some work.' hello
------------
Here, we just added another line to "hello", and we used a shorthand for Here, we just added another line to "hello", and we used a shorthand for
both going a "git-update-cache hello" and "git commit" by just giving the both going a "git-update-cache hello" and "git commit" by just giving the
@ -706,15 +739,19 @@ Now, to make it a bit more interesting, let's assume that somebody else
does some work in the original branch, and simulate that by going back does some work in the original branch, and simulate that by going back
to the master branch, and editing the same file differently there: to the master branch, and editing the same file differently there:
git checkout master ------------
git checkout master
------------
Here, take a moment to look at the contents of "hello", and notice how they Here, take a moment to look at the contents of "hello", and notice how they
don't contain the work we just did in "mybranch" - because that work don't contain the work we just did in "mybranch" - because that work
hasn't happened in the "master" branch at all. Then do hasn't happened in the "master" branch at all. Then do
echo "Play, play, play" >>hello ------------
echo "Lots of fun" >>example echo "Play, play, play" >>hello
git commit -m 'Some fun.' hello example echo "Lots of fun" >>example
git commit -m 'Some fun.' hello example
------------
since the master branch is obviously in a much better mood. since the master branch is obviously in a much better mood.
@ -735,7 +772,9 @@ branch (which is currently our HEAD too). To do that, there's a nice
script called "git resolve", which wants to know which branches you want script called "git resolve", which wants to know which branches you want
to resolve and what the merge is all about: to resolve and what the merge is all about:
git resolve HEAD mybranch "Merge work in mybranch" ------------
git resolve HEAD mybranch "Merge work in mybranch"
------------
where the third argument is going to be used as the commit message if where the third argument is going to be used as the commit message if
the merge can be resolved automatically. the merge can be resolved automatically.
@ -761,14 +800,18 @@ should already be well used to if you've ever used CVS, so let's just
open "hello" in our editor (whatever that may be), and fix it up somehow. open "hello" in our editor (whatever that may be), and fix it up somehow.
I'd suggest just making it so that "hello" contains all four lines: I'd suggest just making it so that "hello" contains all four lines:
Hello World ------------
It's a new day for git Hello World
Play, play, play It's a new day for git
Work, work, work Play, play, play
Work, work, work
------------
and once you're happy with your manual merge, just do a and once you're happy with your manual merge, just do a
git commit hello ------------
git commit hello
------------
which will very loudly warn you that you're now committing a merge which will very loudly warn you that you're now committing a merge
(which is correct, so never mind), and you can write a small merge (which is correct, so never mind), and you can write a small merge
@ -781,8 +824,8 @@ switch to it, and continue to work with it if you want to. The
from the "master" branch, git will know how you merged it, so you'll not from the "master" branch, git will know how you merged it, so you'll not
have to do _that_ merge again. have to do _that_ merge again.
Another useful tool, especially if you do not work in X-Window Another useful tool, especially if you do not always work in X-Window
environment all the time, is "git show-branch". environment, is "git show-branch".
------------------------------------------------ ------------------------------------------------
$ git show-branch master mybranch $ git show-branch master mybranch
@ -878,18 +921,20 @@ pull from:
Local directory Local directory
/path/to/repo.git/ /path/to/repo.git/
[ Digression: you could do without using any branches at all, by [NOTE]
keeping as many local repositories as you would like to have You could do without using any branches at all, by
branches, and merging between them with "git pull", just like keeping as many local repositories as you would like to have
you merge between branches. The advantage of this approach is branches, and merging between them with "git pull", just like
that it lets you keep set of files for each "branch" checked you merge between branches. The advantage of this approach is
out and you may find it easier to switch back and forth if you that it lets you keep set of files for each "branch" checked
juggle multiple lines of development simultaneously. Of out and you may find it easier to switch back and forth if you
course, you will pay the price of more disk usage to hold juggle multiple lines of development simultaneously. Of
multiple working trees, but disk space is cheap these days. ] course, you will pay the price of more disk usage to hold
multiple working trees, but disk space is cheap these days.
[ Digression #2: you could even pull from your own repository by [NOTE]
giving '.' as <remote-repository> parameter to "git pull". ] You could even pull from your own repository by
giving '.' as <remote-repository> parameter to "git pull".
It is likely that you will be pulling from the same remote It is likely that you will be pulling from the same remote
repository from time to time. As a short hand, you can store repository from time to time. As a short hand, you can store
@ -916,15 +961,15 @@ EOF
Examples. Examples.
(1) git pull linus . git pull linus
(2) git pull linus tag v0.99.1 . git pull linus tag v0.99.1
(3) git pull jgarzik/netdev-2.6.git/ e100 . git pull jgarzik/netdev-2.6.git/ e100
the above are equivalent to: the above are equivalent to:
(1) git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD . git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD
(2) git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1 . git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1
(3) git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100 . git pull http://www.kernel.org/pub/.../jgarzik/netdev-2.6.git e100
Publishing your work Publishing your work
@ -944,8 +989,9 @@ changes you made in your primary working tree are in good shape,
update the public repository from it. This is often called update the public repository from it. This is often called
"pushing". "pushing".
[ Side note: this public repository could further be mirrored, [NOTE]
and that is how kernel.org git repositories are done. ] This public repository could further be mirrored,
and that is how kernel.org git repositories are done.
Publishing the changes from your local (private) repository to Publishing the changes from your local (private) repository to
your remote (public) repository requires a write privilege on your remote (public) repository requires a write privilege on
@ -958,10 +1004,11 @@ repository will be populated and be kept up-to-date by pushing
into it later. Obviously, this repository creation needs to be into it later. Obviously, this repository creation needs to be
done only once. done only once.
[ Digression: "git push" uses a pair of programs, [NOTE]
"git-send-pack" on your local machine, and "git-receive-pack" "git push" uses a pair of programs,
on the remote machine. The communication between the two over "git-send-pack" on your local machine, and "git-receive-pack"
the network internally uses an SSH connection. ] on the remote machine. The communication between the two over
the network internally uses an SSH connection.
Your private repository's GIT directory is usually .git, but Your private repository's GIT directory is usually .git, but
your public repository is often named after the project name, your public repository is often named after the project name,
@ -982,12 +1029,13 @@ changes to be pulled by via the transport of your choice. Also
you need to make sure that you have the "git-receive-pack" you need to make sure that you have the "git-receive-pack"
program on the $PATH. program on the $PATH.
[ Side note: many installations of sshd do not invoke your shell [NOTE]
as the login shell when you directly run programs; what this Many installations of sshd do not invoke your shell
means is that if your login shell is bash, only .bashrc is as the login shell when you directly run programs; what this
read and not .bash_profile. As a workaround, make sure means is that if your login shell is bash, only .bashrc is
.bashrc sets up $PATH so that you can run 'git-receive-pack' read and not .bash_profile. As a workaround, make
program. ] sure .bashrc sets up $PATH so that you can run 'git-receive-pack'
program.
Your "public repository" is now ready to accept your changes. Your "public repository" is now ready to accept your changes.
Come back to the machine you have your private repository. From Come back to the machine you have your private repository. From
@ -1024,13 +1072,14 @@ directories by now. "git repack" tells you how many objects it
packed, and stores the packed file in .git/objects/pack packed, and stores the packed file in .git/objects/pack
directory. directory.
[ Side Note: you will see two files, pack-*.pack and pack-*.idx, [NOTE]
in .git/objects/pack directory. They are closely related to You will see two files, pack-\*.pack and pack-\*.idx,
each other, and if you ever copy them by hand to a different in .git/objects/pack directory. They are closely related to
repository for whatever reason, you should make sure you copy each other, and if you ever copy them by hand to a different
them together. The former holds all the data from the objects repository for whatever reason, you should make sure you copy
in the pack, and the latter holds the index for random them together. The former holds all the data from the objects
access. ] in the pack, and the latter holds the index for random
access.
If you are paranoid, running "git-verify-pack" command would If you are paranoid, running "git-verify-pack" command would
detect if you have a corrupt pack, but do not worry too much. detect if you have a corrupt pack, but do not worry too much.
@ -1046,11 +1095,12 @@ would remove them for you.
You can try running "find .git/objects -type f" before and after You can try running "find .git/objects -type f" before and after
you run "git prune-packed" if you are curious. you run "git prune-packed" if you are curious.
[ Side Note: "git pull" is slightly cumbersome for HTTP transport, [NOTE]
as a packed repository may contain relatively few objects in a "git pull" is slightly cumbersome for HTTP transport,
relatively large pack. If you expect many HTTP pulls from your as a packed repository may contain relatively few objects in a
public repository you might want to repack & prune often, or relatively large pack. If you expect many HTTP pulls from your
never. ] public repository you might want to repack & prune often, or
never.
If you run "git repack" again at this point, it will say If you run "git repack" again at this point, it will say
"Nothing to pack". Once you continue your development and "Nothing to pack". Once you continue your development and
@ -1083,93 +1133,92 @@ from only one remote repository.
A recommended workflow for a "project lead" goes like this: A recommended workflow for a "project lead" goes like this:
(1) Prepare your primary repository on your local machine. Your 1. Prepare your primary repository on your local machine. Your
work is done there. work is done there.
(2) Prepare a public repository accessible to others. 2. Prepare a public repository accessible to others.
(3) Push into the public repository from your primary 3. Push into the public repository from your primary
repository. repository.
(4) "git repack" the public repository. This establishes a big 4. "git repack" the public repository. This establishes a big
pack that contains the initial set of objects as the pack that contains the initial set of objects as the
baseline, and possibly "git prune-packed" if the transport baseline, and possibly "git prune-packed" if the transport
used for pulling from your repository supports packed used for pulling from your repository supports packed
repositories. repositories.
(5) Keep working in your primary repository. Your changes 5. Keep working in your primary repository. Your changes
include modifications of your own, patches you receive via include modifications of your own, patches you receive via
e-mails, and merges resulting from pulling the "public" e-mails, and merges resulting from pulling the "public"
repositories of your "subsystem maintainers". repositories of your "subsystem maintainers".
+
You can repack this private repository whenever you feel like.
You can repack this private repository whenever you feel 6. Push your changes to the public repository, and announce it
like. to the public.
(6) Push your changes to the public repository, and announce it 7. Every once in a while, "git repack" the public repository.
to the public. Go back to step 5. and continue working.
(7) Every once in a while, "git repack" the public repository.
Go back to step (5) and continue working.
A recommended work cycle for a "subsystem maintainer" who works A recommended work cycle for a "subsystem maintainer" who works
on that project and has an own "public repository" goes like this: on that project and has an own "public repository" goes like this:
(1) Prepare your work repository, by "git clone" the public 1. Prepare your work repository, by "git clone" the public
repository of the "project lead". The URL used for the repository of the "project lead". The URL used for the
initial cloning is stored in .git/branches/origin. initial cloning is stored in .git/branches/origin.
(2) Prepare a public repository accessible to others. 2. Prepare a public repository accessible to others.
(3) Copy over the packed files from "project lead" public 3. Copy over the packed files from "project lead" public
repository to your public repository by hand; preferrably repository to your public repository by hand; preferrably
use rsync for that task. use rsync for that task.
(4) Push into the public repository from your primary 4. Push into the public repository from your primary
repository. Run "git repack", and possibly "git repository. Run "git repack", and possibly "git
prune-packed" if the transport used for pulling from your prune-packed" if the transport used for pulling from your
repository supports packed repositories. repository supports packed repositories.
(5) Keep working in your primary repository. Your changes 5. Keep working in your primary repository. Your changes
include modifications of your own, patches you receive via include modifications of your own, patches you receive via
e-mails, and merges resulting from pulling the "public" e-mails, and merges resulting from pulling the "public"
repositories of your "project lead" and possibly your repositories of your "project lead" and possibly your
"sub-subsystem maintainers". "sub-subsystem maintainers".
+
You can repack this private repository whenever you feel
like.
You can repack this private repository whenever you feel 6. Push your changes to your public repository, and ask your
like. "project lead" and possibly your "sub-subsystem
maintainers" to pull from it.
(6) Push your changes to your public repository, and ask your 7. Every once in a while, "git repack" the public repository.
"project lead" and possibly your "sub-subsystem Go back to step 5. and continue working.
maintainers" to pull from it.
(7) Every once in a while, "git repack" the public repository.
Go back to step (5) and continue working.
A recommended work cycle for an "individual developer" who does A recommended work cycle for an "individual developer" who does
not have a "public" repository is somewhat different. It goes not have a "public" repository is somewhat different. It goes
like this: like this:
(1) Prepare your work repository, by "git clone" the public 1. Prepare your work repository, by "git clone" the public
repository of the "project lead" (or a "subsystem repository of the "project lead" (or a "subsystem
maintainer", if you work on a subsystem). The URL used for maintainer", if you work on a subsystem). The URL used for
the initial cloning is stored in .git/branches/origin. the initial cloning is stored in .git/branches/origin.
(2) Do your work there. Make commits. 2. Do your work there. Make commits.
(3) Run "git fetch origin" from the public repository of your 3. Run "git fetch origin" from the public repository of your
upstream every once in a while. This does only the first upstream every once in a while. This does only the first
half of "git pull" but does not merge. The head of the half of "git pull" but does not merge. The head of the
public repository is stored in .git/refs/heads/origin. public repository is stored in .git/refs/heads/origin.
(4) Use "git cherry origin" to see which ones of your patches 4. Use "git cherry origin" to see which ones of your patches
were accepted, and/or use "git rebase origin" to port your were accepted, and/or use "git rebase origin" to port your
unmerged changes forward to the updated upstream. unmerged changes forward to the updated upstream.
(5) Use "git format-patch origin" to prepare patches for e-mail 5. Use "git format-patch origin" to prepare patches for e-mail
submission to your upstream and send it out. Go back to submission to your upstream and send it out. Go back to
step (2) and continue. step (2) and continue.
Working with Others, Shared Repository Style Working with Others, Shared Repository Style

144
README
View file

@ -15,7 +15,7 @@
- "goddamn idiotic truckload of sh*t": when it breaks - "goddamn idiotic truckload of sh*t": when it breaks
This is a stupid (but extremely fast) directory content manager. It This is a stupid (but extremely fast) directory content manager. It
doesn't do a whole lot, but what it _does_ do is track directory doesn't do a whole lot, but what it 'does' do is track directory
contents efficiently. contents efficiently.
There are two object abstractions: the "object database", and the There are two object abstractions: the "object database", and the
@ -66,9 +66,11 @@ Regardless of object type, all objects share the following
characteristics: they are all deflated with zlib, and have a header characteristics: they are all deflated with zlib, and have a header
that not only specifies their tag, but also provides size information that not only specifies their tag, but also provides size information
about the data in the object. It's worth noting that the SHA1 hash 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. 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 (Historical note: in the dawn of the age of git the hash
was the sha1 of the _compressed_ object) was the sha1 of the 'compressed' object.)
As a result, the general consistency of an object can always be tested 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 independently of the contents or the type of the object: all objects can
@ -79,7 +81,7 @@ size> + <byte\0> + <binary object data>.
The structured objects can further have their structure and The structured objects can further have their structure and
connectivity to other objects verified. This is generally done with connectivity to other objects verified. This is generally done with
the "git-fsck-cache" program, which generates a full dependency graph the `git-fsck-cache` program, which generates a full dependency graph
of all objects, and verifies their internal consistency (in addition of all objects, and verifies their internal consistency (in addition
to just verifying their superficial consistency through the hash). to just verifying their superficial consistency through the hash).
@ -89,7 +91,7 @@ Blob Object
~~~~~~~~~~~ ~~~~~~~~~~~
A "blob" object is nothing but a binary blob of data, and doesn't 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 refer to anything else. There is no signature or any other
verification of the data, so while the object is consistent (it _is_ 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 indexed by its sha1 hash, so the data itself is certainly correct), it
has absolutely no other attributes. No name associations, no has absolutely no other attributes. No name associations, no
permissions. It is purely a blob of data (i.e. normally "file permissions. It is purely a blob of data (i.e. normally "file
@ -125,7 +127,7 @@ 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 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 can trust the contents of a blob, but you don't know where those
contents _came_ from. contents 'came' from.
Side note on trees: since a "tree" object is a sorted list of Side note on trees: since a "tree" object is a sorted list of
"filename+content", you can create a diff between two trees without "filename+content", you can create a diff between two trees without
@ -142,7 +144,8 @@ noticing that the blob stayed the same. However, renames with data
changes need a smarter "diff" implementation. changes need a smarter "diff" implementation.
A tree is created with link:git-write-tree.html[git-write-tree] and A tree is created with link:git-write-tree.html[git-write-tree] and
its data can be accessed by link:git-ls-tree.html[git-ls-tree] its data can be accessed by link:git-ls-tree.html[git-ls-tree].
Two trees can be compared with link:git-diff-tree.html[git-diff-tree].
Commit Object Commit Object
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -161,19 +164,19 @@ The parents do not have to actually have any relationship with the
result, for example. result, for example.
Note on commits: unlike real SCM's, commits do not contain Note on commits: unlike real SCM's, commits do not contain
rename information or file mode chane information. All of that is rename information or file mode change information. All of that is
implicit in the trees involved (the result tree, and the result trees implicit in the trees involved (the result tree, and the result trees
of the parents), and describing that makes no sense in this idiotic of the parents), and describing that makes no sense in this idiotic
file manager. file manager.
A commit is created with link:git-commit-tree.html[git-commit-tree] and A commit is created with link:git-commit-tree.html[git-commit-tree] and
its data can be accessed by link:git-cat-file.html[git-cat-file] its data can be accessed by link:git-cat-file.html[git-cat-file].
Trust Trust
~~~~~ ~~~~~
An aside on the notion of "trust". Trust is really outside the scope 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 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 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 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 of an object uniquely identifies a known state - just not a state that
you may want to trust. you may want to trust.
@ -185,7 +188,7 @@ of history, with full contents. You can't later fake any step of the
way once you have the name of a commit. way once you have the name of a commit.
So to introduce some real trust in the system, the only thing you need 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 to do is to digitally sign just 'one' special note, which includes the
name of a top-level commit. Your digital signature shows others name of a top-level commit. Your digital signature shows others
that you trust that commit, and the immutability of the history of that you trust that commit, and the immutability of the history of
commits tells others that they can trust the whole history. commits tells others that they can trust the whole history.
@ -212,8 +215,10 @@ Note that despite the tag features, "git" itself only handles content
integrity; the trust framework (and signature provision and integrity; the trust framework (and signature provision and
verification) has to come from outside. verification) has to come from outside.
A tag is created with link:git-mktag.html[git-mktag] and A tag is created with link:git-mktag.html[git-mktag],
its data can be accessed by link:git-cat-file.html[git-cat-file] its data can be accessed by link:git-cat-file.html[git-cat-file],
and the signature can be verified by
link:git-verify-tag-script.html[git-verify-tag].
The "index" aka "Current Directory Cache" The "index" aka "Current Directory Cache"
@ -228,7 +233,7 @@ meaning, and can be partially updated at any time.
In particular, the index certainly does not need to be consistent with In particular, the index certainly does not need to be consistent with
the current directory contents (in fact, most operations will depend on the current directory contents (in fact, most operations will depend on
different ways to make the index _not_ be consistent with the directory different ways to make the index 'not' be consistent with the directory
hierarchy), but it has three very important attributes: hierarchy), but it has three very important attributes:
'(a) it can re-generate the full state it caches (not just the '(a) it can re-generate the full state it caches (not just the
@ -259,7 +264,7 @@ 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 haven't lost any information as long as you have the name of the tree
that it described. that it described.
At the same time, the directory index is at the same time also the At the same time, the index is at the same time also the
staging area for creating new trees, and creating a new tree always staging area for creating new trees, and creating a new tree always
involves a controlled modification of the index file. In particular, involves a controlled modification of the index file. In particular,
the index file can have the representation of an intermediate tree that the index file can have the representation of an intermediate tree that
@ -293,18 +298,18 @@ i.e. it will normally just update existing cache entries.
To tell git that yes, you really do realize that certain files no To tell git that yes, you really do realize that certain files no
longer exist in the archive, or that new files should be added, you longer exist in the archive, or that new files should be added, you
should use the "--remove" and "--add" flags respectively. should use the `--remove` and `--add` flags respectively.
NOTE! A "--remove" flag does _not_ mean that subsequent filenames will NOTE! A `--remove` flag does 'not' mean that subsequent filenames will
necessarily be removed: if the files still exist in your directory necessarily be removed: if the files still exist in your directory
structure, the index will be updated with their new status, not structure, the index will be updated with their new status, not
removed. The only thing "--remove" means is that update-cache will be 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 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. does not exist any more, it will update the index accordingly.
As a special case, you can also do "git-update-cache --refresh", which As a special case, you can also do `git-update-cache --refresh`, which
will refresh the "stat" information of each index to match the current will refresh the "stat" information of each index to match the current
stat information. It will _not_ update the object status itself, and stat information. It will 'not' update the object status itself, and
it will only update the fields that are used to quickly test whether it will only update the fields that are used to quickly test whether
an object still matches its old backing store object. an object still matches its old backing store object.
@ -332,7 +337,7 @@ index. Normal operation is just
git-read-tree <sha1 of tree> git-read-tree <sha1 of tree>
and your index file will now be equivalent to the tree that you saved and your index file will now be equivalent to the tree that you saved
earlier. However, that is only your _index_ file: your working earlier. However, that is only your 'index' file: your working
directory contents have not been modified. directory contents have not been modified.
4) index -> working directory 4) index -> working directory
@ -342,20 +347,21 @@ You update your working directory from the index by "checking out"
files. This is not a very common operation, since normally you'd just files. This is not a very common operation, since normally you'd just
keep your files updated, and rather than write to your working keep your files updated, and rather than write to your working
directory, you'd tell the index files about the changes in your directory, you'd tell the index files about the changes in your
working directory (i.e. "git-update-cache"). working directory (i.e. `git-update-cache`).
However, if you decide to jump to a new version, or check out somebody 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 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 index file with read-tree, and then you need to check out the result
with with
git-checkout-cache filename git-checkout-cache filename
or, if you want to check out all of the index, use "-a". or, if you want to check out all of the index, use `-a`.
NOTE! git-checkout-cache normally refuses to overwrite old files, so NOTE! git-checkout-cache normally refuses to overwrite old files, so
if you have an old version of the tree already checked out, you will if you have an old version of the tree already checked out, you will
need to use the "-f" flag (_before_ the "-a" flag or the filename) to need to use the "-f" flag ('before' the "-a" flag or the filename) to
_force_ the checkout. 'force' the checkout.
Finally, there are a few odds and ends which are not purely moving Finally, there are a few odds and ends which are not purely moving
@ -388,9 +394,9 @@ redirection from a pipe or file, or by just typing it at the tty).
git-commit-tree will return the name of the object that represents git-commit-tree will return the name of the object that represents
that commit, and you should save it away for later use. Normally, that commit, and you should save it away for later use. Normally,
you'd commit a new "HEAD" state, and while git doesn't care where you you'd commit a new `HEAD` state, and while git doesn't care where you
save the note about that state, in practice we tend to just write the save the note about that state, in practice we tend to just write the
result to the file ".git/HEAD", so that we can always see what the result to the file `.git/HEAD`, so that we can always see what the
last committed state was. last committed state was.
6) Examining the data 6) Examining the data
@ -406,16 +412,16 @@ object:
shows the type of the object, and once you have the type (which is shows the type of the object, and once you have the type (which is
usually implicit in where you find the object), you can use usually implicit in where you find the object), you can use
git-cat-file blob|tree|commit <objectname> git-cat-file blob|tree|commit|tag <objectname>
to show its contents. NOTE! Trees have binary content, and as a result to show its contents. NOTE! Trees have binary content, and as a result
there is a special helper for showing that content, called there is a special helper for showing that content, called
"git-ls-tree", which turns the binary content into a more easily `git-ls-tree`, which turns the binary content into a more easily
readable form. readable form.
It's especially instructive to look at "commit" objects, since those It's especially instructive to look at "commit" objects, since those
tend to be small and fairly self-explanatory. In particular, if you tend to be small and fairly self-explanatory. In particular, if you
follow the convention of having the top commit name in ".git/HEAD", follow the convention of having the top commit name in `.git/HEAD`,
you can do you can do
git-cat-file commit $(cat .git/HEAD) git-cat-file commit $(cat .git/HEAD)
@ -453,30 +459,88 @@ object.
Once you know the three trees you are going to merge (the one 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 "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 the branches you want to merge), you do a "merge" read into the
index. This will throw away your old index contents, so you should 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 always do a merge against your last commit (which should thus match
what you have in your current index anyway). what you have in your current index anyway).
To do the merge, do To do the merge, do
git-read-tree -m <origtree> <target1tree> <target2tree> git-read-tree -m -u <origtree> <yourtree> <targettree>
which will do all trivial merge operations for you directly in the which will do all trivial merge operations for you directly in the
index file, and you can just write the result out with index file, and you can just write the result out with
"git-write-tree". `git-write-tree`.
NOTE! Because the merge is done in the index file, and not in your Historical note. We did not have `-u` facility when this
working directory, your working directory will no longer match your section was first written, so we used to warn that
index. You can use "git-checkout-cache -f -a" to make the effect of the merge is done in the index file, not in your
the merge be seen in your working directory. working directory, and your working directory will no longer match your
index.
NOTE2! Sadly, many merges aren't trivial. If there are files that have
8) Merging multiple trees, continued
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 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 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 object, and you will have to resolve any such merge clashes using
other tools before you can write out the result. other tools before you can write out the result.
You can examine such index state with `git-ls-files --unmerged`
command. An example:
[ fixme: talk about resolving merges here ] ------------------------------------------------
$ git-read-tree -m $orig HEAD $target
$ git-ls-files --unmerged
100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello.c
100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello.c
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello.c
------------------------------------------------
Each line of the `git-ls-files --unmerged` output begins with
the blob mode bits, blob SHA1, 'stage number', and the
filename. The 'stage number' is git's way to say which tree it
came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
tree, and stage3 `$target` tree.
Earlier we said that trivial merges are done inside
`git-read-tree -m`. For example, if the file did not change
from `$orig` to `HEAD` nor `$target`, or if the file changed
from `$orig` to `HEAD` and `$orig` to `$target` the same way,
obviously the final outcome is what is in `HEAD`. What the
above example shows is that file `hello.c` was changed from
`$orig` to `HEAD` and `$orig` to `$target` in a different way.
You could resolve this by running your favorite 3-way merge
program, e.g. `diff3` or `merge`, on the blob objects from
these three stages yourself, like this:
------------------------------------------------
$ git-cat-file blob 263414f... >hello.c~1
$ git-cat-file blob 06fa6a2... >hello.c~2
$ git-cat-file blob cc44c73... >hello.c~3
$ merge hello.c~2 hello.c~1 hello.c~3
------------------------------------------------
This would leave the merge result in `hello.c~2` file, along
with conflict markers if there are conflicts. After verifying
the merge result makes sense, you can tell git what the final
merge result for this file is by:
mv -f hello.c~2 hello.c
git-update-cache hello.c
When a path is in unmerged state, running `git-update-cache` for
that path tells git to mark the path resolved.
The above is the description of a git merge at the lowest level,
to help you understand what conceptually happens under the hood.
In practice, nobody, not even git itself, uses three `git-cat-file`
for this. There is `git-merge-cache` program that extracts the
stages to temporary files and calls a `merge` script on it
git-merge-cache git-merge-one-file-script hello.c
and that is what higher level `git resolve` is implemented with.