mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
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:
parent
cc9f24d024
commit
8db9307c9c
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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].
|
||||||
|
|
|
@ -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
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
------
|
------
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
144
README
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue