From: Petr Baudis Date: Wed, 11 May 2005 00:00:49 +0000 (+0200) Subject: Merge with http://members.cox.net/junkio/git-jc.git X-Git-Tag: v0.99~603 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=f1a7eb36b017c62d9a007b6b8660bdeec3f94f97;hp=883550481f885ab2865ab71819167230d21d4c14;p=git.git Merge ... http://members.cox.net/junkio/git-jc.git --- diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 00000000..b23991d5 --- /dev/null +++ b/Documentation/Makefile @@ -0,0 +1,24 @@ +DOC_SRC=$(wildcard git*.txt) +DOC_HTML=$(patsubst %.txt,%.html,$(DOC_SRC)) +DOC_MAN=$(patsubst %.txt,%.1,$(DOC_SRC)) + +all: $(DOC_HTML) $(DOC_MAN) + +html: $(DOC_HTML) + +man: $(DOC_MAN) + +git-%: %.c $(LIB_FILE) + $(CC) $(CFLAGS) -o $@ $(filter %.c,$^) $(LIBS) + +clean: + rm -f *.xml *.html *.1 + +%.html : %.txt + asciidoc -b css-embedded -d manpage $< + +%.1 : %.xml + xmlto man $< + +%.xml : %.txt + asciidoc -b docbook -d manpage $< diff --git a/Documentation/core-git.txt b/Documentation/core-git.txt deleted file mode 100644 index 8bd89319..00000000 --- a/Documentation/core-git.txt +++ /dev/null @@ -1,1307 +0,0 @@ -This file contains reference information for the core git commands. - -The README contains much useful definition and clarification -info - read that first. And of the commands, I suggest reading -'git-update-cache' and 'git-read-tree' first - I wish I had! - -David Greaves -24/4/05 - -Updated by Junio C Hamano on 2005-05-05 to -reflect recent changes. - -Identifier terminology used: - - - Indicates any object sha1 identifier - - - Indicates a blob object sha1 identifier - - - Indicates a tree object sha1 identifier - - - Indicates a commit object sha1 identifier - - - Indicates a tree, commit or tag object sha1 identifier. - A command that takes a argument ultimately - wants to operate on a object but automatically - dereferences and that points at a - . - - - Indicates that an object type is required. - Currently one of: blob/tree/commit/tag - - - Indicates a filename - always relative to the root of - the tree structure GIT_INDEX_FILE describes. - - -################################################################ -git-apply-patch-script - -This is a sample script to be used as GIT_EXTERNAL_DIFF to apply -differences git-diff-* family of commands reports to the current -work tree. - - -################################################################ -git-cat-file - git-cat-file (-t | ) - -Provides contents or type of objects in the repository. The type -is required if -t is not being used to find the object type. - - - The sha1 identifier of the object. - --t - Instead of the content, show the object type identified - by . - - - Typically this matches the real type of but - asking for type that can trivially dereferenced from the - given is also permitted. An example is to ask - "tree" with for a commit object that contains - it, or to ask "blob" with for a tag object that - points at it. - -Output - -If -t is specified, one of the . - -Otherwise the raw (though uncompressed) contents of the will -be returned. - - -################################################################ -git-check-files - git-check-files ... - -Check that a list of files are up-to-date between the filesystem and -the cache. Used to verify a patch target before doing a patch. - -Files that do not exist on the filesystem are considered up-to-date -(whether or not they are in the cache). - -Emits an error message on failure. -preparing to update existing file not in cache - exists but is not in the cache - -preparing to update file not uptodate in cache - on disk is not up-to-date with the cache - -Exits with a status code indicating success if all files are -up-to-date. - -see also: git-update-cache - - -################################################################ -git-checkout-cache - git-checkout-cache [-q] [-a] [-f] [-n] [--prefix=] - [--] ... - -Will copy all files listed from the cache to the working directory -(not overwriting existing files). - --q - be quiet if files exist or are not in the cache - --f - forces overwrite of existing files - --a - checks out all files in the cache (will then continue to - process listed files). - --n - Don't checkout new files, only refresh files already checked - out. - ---prefix= - When creating files, prepend (usually a directory - including a trailing /) - --- - Do not interpret any more arguments as options. - -Note that the order of the flags matters: - - git-checkout-cache -a -f file.c - -will first check out all files listed in the cache (but not overwrite -any old ones), and then force-checkout file.c a second time (ie that -one _will_ overwrite any old contents with the same filename). - -Also, just doing "git-checkout-cache" does nothing. You probably meant -"git-checkout-cache -a". And if you want to force it, you want -"git-checkout-cache -f -a". - -Intuitiveness is not the goal here. Repeatability is. The reason for -the "no arguments means no work" thing is that from scripts you are -supposed to be able to do things like - - find . -name '*.h' -print0 | xargs -0 git-checkout-cache -f -- - -which will force all existing *.h files to be replaced with their -cached copies. If an empty command line implied "all", then this would -force-refresh everything in the cache, which was not the point. - -To update and refresh only the files already checked out: - - git-checkout-cache -n -f -a && git-update-cache --ignore-missing --refresh - -Oh, and the "--" is just a good idea when you know the rest will be -filenames. Just so that you wouldn't have a filename of "-a" causing -problems (not possible in the above example, but get used to it in -scripting!). - -The prefix ability basically makes it trivial to use git-checkout-cache as -a "git-export as tree" function. Just read the desired tree into the -index, and do a - - git-checkout-cache --prefix=git-export-dir/ -a - -and git-checkout-cache will "git-export" the cache into the specified -directory. - -NOTE! The final "/" is important. The git-exported name is literally just -prefixed with the specified string, so you can also do something like - - git-checkout-cache --prefix=.merged- Makefile - -to check out the currently cached copy of "Makefile" into the file -".merged-Makefile". - - -################################################################ -git-commit-tree - git-commit-tree [-p ]* < changelog - -Creates a new commit object based on the provided tree object and -emits the new commit object id on stdout. If no parent is given then -it is considered to be an initial tree. - -A commit object usually has 1 parent (a commit after a change) or up -to 16 parents. More than one parent represents a merge of branches -that led to them. - -While a tree represents a particular directory state of a working -directory, a commit represents that state in "time", and explains how -to get there. - -Normally a commit would identify 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 result to the file ".git/HEAD", so that we can -always see what the last committed state was. - -Options - - - An existing tree object - --p - Each -p indicates a the id of a parent commit object. - - -Commit Information - -A commit encapsulates: - all parent object ids - author name, email and date - committer name and email and the commit time. - -If not provided, git-commit-tree uses your name, hostname and domain to -provide author and committer info. This can be overridden using the -following environment variables. - AUTHOR_NAME - AUTHOR_EMAIL - AUTHOR_DATE - COMMIT_AUTHOR_NAME - COMMIT_AUTHOR_EMAIL -(nb <,> and '\n's are stripped) - -A commit comment is read from stdin (max 999 chars). If a changelog -entry is not provided via '<' redirection, git-commit-tree will just wait -for one to be entered and terminated with ^D - -see also: git-write-tree - - -################################################################ -git-convert-cache - -Converts old-style GIT repository to the latest. - - -################################################################ -git-diff-cache - git-diff-cache [-p] [-r] [-z] [--cached] - -Compares the content and mode of the blobs found via a tree object -with the content of the current cache and, optionally ignoring the -stat state of the file on disk. - - - The id of a tree object to diff against. - --p - Generate patch (see section on generating patches) - --r - This flag does not mean anything. It is there only to match - git-diff-tree. Unlike git-diff-tree, git-diff-cache always looks - at all the subdirectories. - --z - \0 line termination on output - ---cached - do not consider the on-disk file at all - -Output format: - -See "Output format from git-diff-cache, git-diff-tree and git-diff-files" -section. - -Operating Modes - -You can choose whether you want to trust the index file entirely -(using the "--cached" flag) or ask the diff logic to show any files -that don't match the stat state as being "tentatively changed". Both -of these operations are very useful indeed. - -Cached Mode - -If --cached is specified, it allows you to ask: - - show me the differences between HEAD and the current index - contents (the ones I'd write with a "git-write-tree") - -For example, let's say that you have worked on your index file, and are -ready to commit. You want to see eactly _what_ you are going to commit is -without having to write a new tree object and compare it that way, and to -do that, you just do - - git-diff-cache --cached $(cat .git/HEAD) - -Example: let's say I had renamed "commit.c" to "git-commit.c", and I had -done an "git-update-cache" to make that effective in the index file. -"git-diff-files" wouldn't show anything at all, since the index file -matches my working directory. But doing a git-diff-cache does: - - torvalds@ppc970:~/git> git-diff-cache --cached $(cat .git/HEAD) - -100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c - +100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c - -You can trivially see that the above is a rename. - -In fact, "git-diff-cache --cached" _should_ always be entirely equivalent to -actually doing a "git-write-tree" and comparing that. Except this one is much -nicer for the case where you just want to check where you are. - -So doing a "git-diff-cache --cached" is basically very useful when you are -asking yourself "what have I already marked for being committed, and -what's the difference to a previous tree". - -Non-cached Mode - -The "non-cached" mode takes a different approach, and is potentially the -even more useful of the two in that what it does can't be emulated with a -"git-write-tree + git-diff-tree". Thus that's the default mode. The -non-cached version asks the question - - "show me the differences between HEAD and the currently checked out - tree - index contents _and_ files that aren't up-to-date" - -which is obviously a very useful question too, since that tells you what -you _could_ commit. Again, the output matches the "git-diff-tree -r" -output to a tee, but with a twist. - -The twist is that if some file doesn't match the cache, we don't have a -backing store thing for it, and we use the magic "all-zero" sha1 to show -that. So let's say that you have edited "kernel/sched.c", but have not -actually done an git-update-cache on it yet - there is no "object" associated -with the new state, and you get: - - torvalds@ppc970:~/v2.6/linux> git-diff-cache $(cat .git/HEAD ) - *100644->100664 blob 7476bb......->000000...... kernel/sched.c - -ie it shows that the tree has changed, and that "kernel/sched.c" has is -not up-to-date and may contain new stuff. The all-zero sha1 means that to -get the real diff, you need to look at the object in the working directory -directly rather than do an object-to-object diff. - -NOTE! As with other commands of this type, "git-diff-cache" does not -actually look at the contents of the file at all. So maybe -"kernel/sched.c" hasn't actually changed, and it's just that you touched -it. In either case, it's a note that you need to upate-cache it to make -the cache be in sync. - -NOTE 2! You can have a mixture of files show up as "has been updated" and -"is still dirty in the working directory" together. You can always tell -which file is in which state, since the "has been updated" ones show a -valid sha1, and the "not in sync with the index" ones will always have the -special all-zero sha1. - - -################################################################ -git-diff-tree - git-diff-tree [-p] [-r] [-z] [--stdin] [-m] [-s] [-v] []* - -Compares the content and mode of the blobs found via two tree objects. - -Note that git-diff-tree can use the tree encapsulated in a commit object. - - - The id of a tree object. - - - If provided, the results are limited to a subset of files - matching one of these prefix strings. - ie file matches /^||.../ - Note that pattern does not provide any wildcard or regexp - features. - --p - generate patch (see section on generating patches). For - git-diff-tree, this flag implies -r as well. - --r - recurse - --z - \0 line termination on output - ---stdin - When --stdin is specified, the command does not take - arguments from the command line. Instead, it - reads either one or a pair of - separated with a single space from its standard input. - - When a single commit is given on one line of such input, - it compares the commit with its parents. The following - flags further affects its behaviour. This does not - apply to the case where two separated with a - single space are given. - --m - By default, "git-diff-tree --stdin" does not show - differences for merge commits. With this flag, it shows - differences to that commit from all of its parents. - --s - By default, "git-diff-tree --stdin" shows differences, - either in machine-readable form (without -p) or in patch - form (with -p). This output can be supressed. It is - only useful with -v flag. - --v - This flag causes "git-diff-tree --stdin" to also show - the commit message before the differences. - - -Limiting Output - -If you're only interested in differences in a subset of files, for -example some architecture-specific files, you might do: - - git-diff-tree -r arch/ia64 include/asm-ia64 - -and it will only show you what changed in those two directories. - -Or if you are searching for what changed in just kernel/sched.c, just do - - git-diff-tree -r kernel/sched.c - -and it will ignore all differences to other files. - -The pattern is always the prefix, and is matched exactly. There are no -wildcards. Even stricter, it has to match complete path comonent. -I.e. "foo" does not pick up "foobar.h". "foo" does match "foo/bar.h" -so it can be used to name subdirectories. - -Output format: - -See "Output format from git-diff-cache, git-diff-tree and git-diff-files" -section. - -An example of normal usage is: - - torvalds@ppc970:~/git> git-diff-tree 5319e4...... - *100664->100664 blob ac348b.......->a01513....... git-fsck-cache.c - -which tells you that the last commit changed just one file (it's from -this one: - - commit 3c6f7ca19ad4043e9e72fa94106f352897e651a8 - tree 5319e4d609cdd282069cc4dce33c1db559539b03 - parent b4e628ea30d5ab3606119d2ea5caeab141d38df7 - author Linus Torvalds Sat Apr 9 12:02:30 2005 - committer Linus Torvalds Sat Apr 9 12:02:30 2005 - - Make "git-fsck-cache" print out all the root commits it finds. - - Once I do the reference tracking, I'll also make it print out all the - HEAD commits it finds, which is even more interesting. - -in case you care). - - -################################################################ -git-diff-tree-helper - git-diff-tree-helper [-z] [-R] - -Reads output from git-diff-cache, git-diff-tree and git-diff-files and -generates patch format output. - --z - \0 line termination on input - --R - Output diff in reverse. This is useful for displaying output from - git-diff-cache which always compares tree with cache or working - file. E.g. - - git-diff-cache | git-diff-tree-helper -R file.c - - would show a diff to bring the working file back to what is in the - . - -See also the section on generating patches. - - -################################################################ -git-fsck-cache - git-fsck-cache [--tags] [--root] [[--unreachable] [--cache] *] - -Verifies the connectivity and validity of the objects in the database. - - - An object to treat as the head of an unreachability trace. - ---unreachable - Print out objects that exist but that aren't readable from any - of the specified head nodes. - ---root - Report root nodes. - ---tags - Report tags. - ---cache - Consider any object recorded in the cache also as a head node for - an unreachability trace. - -It tests SHA1 and general object sanity, and it does full tracking of -the resulting reachability and everything else. It prints out any -corruption it finds (missing or bad objects), and if you use the -"--unreachable" flag it will also print out objects that exist but -that aren't readable from any of the specified head nodes. - -So for example - - git-fsck-cache --unreachable $(cat .git/HEAD) - -or, for Cogito users: - - git-fsck-cache --unreachable $(cat .git/refs/heads/*) - -will do quite a _lot_ of verification on the tree. There are a few -extra validity tests to be added (make sure that tree objects are -sorted properly etc), but on the whole if "git-fsck-cache" is happy, you -do have a valid tree. - -Any corrupt objects you will have to find in backups or other archives -(ie you can just remove them and do an "rsync" with some other site in -the hopes that somebody else has the object you have corrupted). - -Of course, "valid tree" doesn't mean that it wasn't generated by some -evil person, and the end result might be crap. Git is a revision -tracking system, not a quality assurance system ;) - -Extracted Diagnostics - -expect dangling commits - potential heads - due to lack of head information - You haven't specified any nodes as heads so it won't be - possible to differentiate between un-parented commits and - root nodes. - -missing sha1 directory '' - The directory holding the sha1 objects is missing. - -unreachable - The object , isn't actually referred to directly - or indirectly in any of the trees or commits seen. This can - mean that there's another root na SHA1_ode that you're not specifying - or that the tree is corrupt. If you haven't missed a root node - then you might as well delete unreachable nodes since they - can't be used. - -missing - The object , is referred to but isn't present in - the database. - -dangling - The object , is present in the database but never - _directly_ used. A dangling commit could be a root node. - -warning: git-fsck-cache: tree has full pathnames in it - And it shouldn't... - -sha1 mismatch - The database has an object who's sha1 doesn't match the - database value. - This indicates a ??serious?? data integrity problem. - (note: this error occured during early git development when - the database format changed.) - -Environment Variables - -SHA1_FILE_DIRECTORY - used to specify the object database root (usually .git/objects) - -GIT_INDEX_FILE - used to specify the cache - - -################################################################ -git-export - git-export top [base] - -Exports each commit and diff against each of its parents, between -top and base. If base is not specified it exports everything. - - -################################################################ -git-init-db - git-init-db - -This simply creates an empty git object database - basically a .git -directory and .git/object/??/ directories. - -If the object storage directory is specified via the SHA1_FILE_DIRECTORY -environment variable then the sha1 directories are created underneath - -otherwise the default .git/objects directory is used. - -git-init-db won't hurt an existing repository. - - -################################################################ -git-http-pull - - git-http-pull [-c] [-t] [-a] [-v] commit-id url - -Downloads a remote GIT repository via HTTP protocol. - --c - Get the commit objects. --t - Get trees associated with the commit objects. --a - Get all the objects. --v - Report what is downloaded. - - -################################################################ -git-local-pull - - git-local-pull [-c] [-t] [-a] [-l] [-s] [-n] [-v] commit-id path - -Downloads another GIT repository on a local system. - --c - Get the commit objects. --t - Get trees associated with the commit objects. --a - Get all the objects. --v - Report what is downloaded. - -################################################################ -git-ls-tree - git-ls-tree [-r] [-z] - -Converts the tree object to a human readable (and script processable) -form. - - - Id of a tree. - --r - recurse into sub-trees - --z - \0 line termination on output - -Output Format -\t \t \t - - -################################################################ -git-merge-base - git-merge-base - -git-merge-base finds as good a common ancestor as possible. Given a -selection of equally good common ancestors it should not be relied on -to decide in any particular way. - -The git-merge-base algorithm is still in flux - use the source... - - -################################################################ -git-merge-cache - git-merge-cache (-a | -- | *) - -This looks up the (s) in the cache and, if there are any merge -entries, passes the SHA1 hash for those files as arguments 1, 2, 3 (empty -argument if no file), and as argument 4. File modes for the three -files are passed as arguments 5, 6 and 7. - --- - Interpret all future arguments as filenames. - --a - Run merge against all files in the cache that need merging. - -If git-merge-cache is called with multiple s (or -a) then it -processes them in turn only stopping if merge returns a non-zero exit -code. - -Typically this is run with the a script calling the merge command from -the RCS package. - -A sample script called git-merge-one-file-script is included in the -ditribution. - -ALERT ALERT ALERT! The git "merge object order" is different from the -RCS "merge" program merge object order. In the above ordering, the -original is first. But the argument order to the 3-way merge program -"merge" is to have the original in the middle. Don't ask me why. - -Examples: - - torvalds@ppc970:~/merge-test> git-merge-cache cat MM - This is MM from the original tree. # original - This is modified MM in the branch A. # merge1 - This is modified MM in the branch B. # merge2 - This is modified MM in the branch B. # current contents - -or - - torvalds@ppc970:~/merge-test> git-merge-cache cat AA MM - cat: : No such file or directory - This is added AA in the branch A. - This is added AA in the branch B. - This is added AA in the branch B. - fatal: merge program failed - -where the latter example shows how "git-merge-cache" will stop trying to -merge once anything has returned an error (ie "cat" returned an error -for the AA file, because it didn't exist in the original, and thus -"git-merge-cache" didn't even try to merge the MM thing). - -################################################################ -git-merge-one-file-script - -This is the standard helper program to use with git-merge-cache -to resolve a merge after the trivial merge done with git-read-tree -m. - -################################################################ -git-mktag - -Reads a tag contents from its standard input and creates a tag object. -The input must be a well formed tag object. - - -################################################################ -git-prune-script - -This runs git-fsck-cache --unreachable program using the heads specified -on the command line (or .git/refs/heads/* and .git/refs/tags/* if none is -specified), and prunes all unreachable objects from the object database. - - -################################################################ -git-pull-script - -This script is used by Linus to pull from a remote repository and perform -a merge. - - -################################################################ -git-read-tree - git-read-tree ( | -m [ ])" - -Reads the tree information given by into the directory cache, -but does not actually _update_ any of the files it "caches". (see: -git-checkout-cache) - -Optionally, it can merge a tree into the cache or perform a 3-way -merge. - -Trivial merges are done by git-read-tree itself. Only conflicting paths -will be in unmerged state when git-read-tree returns. - --m - Perform a merge, not just a read - - - The id of the tree object(s) to be read/merged. - - -Merging -If -m is specified, git-read-tree performs 2 kinds of merge, a single tree -merge if only 1 tree is given or a 3-way merge if 3 trees are -provided. - -Single Tree Merge -If only 1 tree is specified, git-read-tree operates as if the user did not -specify "-m", except that if the original cache has an entry for a -given pathname; and the contents of the path matches with the tree -being read, the stat info from the cache is used. (In other words, the -cache's stat()s take precedence over the merged tree's) - -That means that if you do a "git-read-tree -m " followed by a -"git-checkout-cache -f -a", the git-checkout-cache only checks out the stuff -that really changed. - -This is used to avoid unnecessary false hits when git-diff-files is -run after git-read-tree. - -3-Way Merge -Each "index" entry has two bits worth of "stage" state. stage 0 is the -normal one, and is the only one you'd see in any kind of normal use. - -However, when you do "git-read-tree" with three trees, the "stage" -starts out at 1. - -This means that you can do - - git-read-tree -m - -and you will end up with an index with all of the entries in -"stage1", all of the entries in "stage2" and all of the - entries in "stage3". - -Furthermore, "git-read-tree" has special-case logic that says: if you see -a file that matches in all respects in the following states, it -"collapses" back to "stage0": - - - stage 2 and 3 are the same; take one or the other (it makes no - difference - the same work has been done on stage 2 and 3) - - - stage 1 and stage 2 are the same and stage 3 is different; take - stage 3 (some work has been done on stage 3) - - - stage 1 and stage 3 are the same and stage 2 is different take - stage 2 (some work has been done on stage 2) - -The git-write-tree command refuses to write a nonsensical tree, and it -will complain about unmerged entries if it sees a single entry that is not -stage 0. - -Ok, this all sounds like a collection of totally nonsensical rules, -but it's actually exactly what you want in order to do a fast -merge. The different stages represent the "result tree" (stage 0, aka -"merged"), the original tree (stage 1, aka "orig"), and the two trees -you are trying to merge (stage 2 and 3 respectively). - -In fact, the way "git-read-tree" works, it's entirely agnostic about how -you assign the stages, and you could really assign them any which way, -and the above is just a suggested way to do it (except since -"git-write-tree" refuses to write anything but stage0 entries, it makes -sense to always consider stage 0 to be the "full merge" state). - -So what happens? Try it out. Select the original tree, and two trees -to merge, and look how it works: - - - if a file exists in identical format in all three trees, it will - automatically collapse to "merged" state by the new git-read-tree. - - - a file that has _any_ difference what-so-ever in the three trees - will stay as separate entries in the index. It's up to "script - policy" to determine how to remove the non-0 stages, and insert a - merged version. But since the index is always sorted, they're easy - to find: they'll be clustered together. - - - the index file saves and restores with all this information, so you - can merge things incrementally, but as long as it has entries in - stages 1/2/3 (ie "unmerged entries") you can't write the result. - -So now the merge algorithm ends up being really simple: - - - you walk the index in order, and ignore all entries of stage 0, - since they've already been done. - - - if you find a "stage1", but no matching "stage2" or "stage3", you - know it's been removed from both trees (it only existed in the - original tree), and you remove that entry. - if you find a - matching "stage2" and "stage3" tree, you remove one of them, and - turn the other into a "stage0" entry. Remove any matching "stage1" - entry if it exists too. .. all the normal trivial rules .. - -Incidentally - it also means that you don't even have to have a separate -subdirectory for this. All the information literally is in the index file, -which is a temporary thing anyway. There is no need to worry about what is -in the working directory, since it is never shown and never used. - -see also: -git-write-tree -git-ls-files - - -################################################################ -git-resolve-script - -This script is used by Linus to merge two trees. - - -################################################################ -git-rev-list - -Lists commit objects in reverse chronological order starting at the -given commit, taking ancestry relationship into account. This is -useful to produce human-readable log output. - - -################################################################ -git-rev-tree - git-rev-tree [--edges] [--cache ] [^] [[^]] - -Provides the revision tree for one or more commits. - ---edges - Show edges (ie places where the marking changes between parent - and child) - ---cache - Use the specified file as a cache from a previous git-rev-list run - to speed things up. Note that this "cache" is totally different - concept from the directory index. Also this option is not - implemented yet. - -[^] - The commit id to trace (a leading caret means to ignore this - commit-id and below) - -Output: - : [: ]* - - - Date in 'seconds since epoch' - - - id of commit object - - - id of each parent commit object (>1 indicates a merge) - - - - The flags are read as a bitmask representing each commit - provided on the commandline. eg: given the command: - - $ git-rev-tree - - The output: - - :5 - - means that is reachable from (1) and (4) - -A revtree can get quite large. git-rev-tree will eventually allow you to -cache previous state so that you don't have to follow the whole thing -down. - -So the change difference between two commits is literally - - git-rev-tree [commit-id1] > commit1-revtree - git-rev-tree [commit-id2] > commit2-revtree - join -t : commit1-revtree commit2-revtree > common-revisions - -(this is also how to find the most common parent - you'd look at just -the head revisions - the ones that aren't referred to by other -revisions - in "common-revision", and figure out the best one. I -think.) - - -################################################################ -git-rpull - - git-rpull [-c] [-t] [-a] [-v] commit-id url - -Pulls from a remote repository over ssh connection, invoking git-rpush on -the other end. - --c - Get the commit objects. --t - Get trees associated with the commit objects. --a - Get all the objects. --v - Report what is downloaded. - - -################################################################ -git-rpush - -Helper "server-side" program used by git-rpull. - - -################################################################ -git-diff-files - git-diff-files [-p] [-q] [-r] [-z] [...] - -Compares the files in the working tree and the cache. When paths -are specified, compares only those named paths. Otherwise all -entries in the cache are compared. The output format is the -same as git-diff-cache and git-diff-tree. - --p - generate patch (see section on generating patches). - --q - Remain silent even on nonexisting files - --r - This flag does not mean anything. It is there only to match - git-diff-tree. Unlike git-diff-tree, git-diff-files always looks - at all the subdirectories. - - -Output format: - -See "Output format from git-diff-cache, git-diff-tree and git-diff-files" -section. - - -################################################################ -git-tag-script - -This is an example script that uses git-mktag to create a tag object -signed with GPG. - - -################################################################ -git-tar-tree - - git-tar-tree [ ] - -Creates a tar archive containing the tree structure for the named tree. -When is specified it is added as a leading path as the files in the -generated tar archive. - - -################################################################ -git-ls-files - git-ls-files [-z] [-t] - (--[cached|deleted|others|ignored|stage|unmerged])* - (-[c|d|o|i|s|u])* - [-x |--exclude=] - [-X |--exclude-from=] - -This merges the file listing in the directory cache index with the -actual working directory list, and shows different combinations of the -two. - -One or more of the options below may be used to determine the files -shown: - --c|--cached - Show cached files in the output (default) - --d|--deleted - Show deleted files in the output - --o|--others - Show other files in the output - --i|--ignored - Show ignored files in the output - Note the this also reverses any exclude list present. - --s|--stage - Show stage files in the output - --u|--unmerged - Show unmerged files in the output (forces --stage) - --z - \0 line termination on output - --x|--exclude= - Skips files matching pattern. - Note that pattern is a shell wildcard pattern. - --X|--exclude-from= - exclude patterns are read from ; 1 per line. - Allows the use of the famous dontdiff file as follows to find - out about uncommitted files just as dontdiff is used with - the diff command: - git-ls-files --others --exclude-from=dontdiff - --t - Identify the file status with the following tags (followed by - a space) at the start of each line: - H cached - M unmerged - R removed/deleted - ? other - -Output -show files just outputs the filename unless --stage is specified in -which case it outputs: - -[ ] - -git-ls-files --unmerged" and "git-ls-files --stage " can be used to examine -detailed information on unmerged paths. - -For an unmerged path, instead of recording a single mode/SHA1 pair, -the dircache records up to three such pairs; one from tree O in stage -1, A in stage 2, and B in stage 3. This information can be used by -the user (or Cogito) to see what should eventually be recorded at the -path. (see read-cache for more information on state) - -see also: -read-cache - - -################################################################ -git-unpack-file - git-unpack-file - -Creates a file holding the contents of the blob specified by sha1. It -returns the name of the temporary file in the following format: - .merge_file_XXXXX - - - Must be a blob id - -################################################################ -git-update-cache - git-update-cache - [--add] [--remove] [--refresh] - [--ignore-missing] - [--force-remove ] - [--cacheinfo ]* - [--] []* - -Modifies the index or directory cache. Each file mentioned is updated -into the cache and any 'unmerged' or 'needs updating' state is -cleared. - -The way git-update-cache handles files it is told about can be modified -using the various options: - ---add - If a specified file isn't in the cache already then it's - added. - Default behaviour is to ignore new files. - ---remove - If a specified file is in the cache but is missing then it's - removed. - Default behaviour is to ignore removed file. - ---refresh - Looks at the current cache and checks to see if merges or - updates are needed by checking stat() information. - ---ignore-missing - Ignores missing files during a --refresh - ---cacheinfo - Directly insert the specified info into the cache. - ---force-remove - Remove the file from the index even when the working directory - still has such a file. - --- - Do not interpret any more arguments as options. - - - Files to act on. - Note that files begining with '.' are discarded. This includes - "./file" and "dir/./file". If you don't want this, then use - cleaner names. - The same applies to directories ending '/' and paths with '//' - -Using --refresh ---refresh does not calculate a new sha1 file or bring the cache -up-to-date for mode/content changes. But what it _does_ do is to -"re-match" the stat information of a file with the cache, so that you -can refresh the cache for a file that hasn't been changed but where -the stat entry is out of date. - -For example, you'd want to do this after doing a "git-read-tree", to link -up the stat cache details with the proper files. - -Using --cacheinfo ---cacheinfo is used to register a file that is not in the current -working directory. This is useful for minimum-checkout merging. - -To pretend you have a file with mode and sha1 at path, say: - - $ git-update-cache --cacheinfo mode sha1 path - -To update and refresh only the files already checked out: - - git-checkout-cache -n -f -a && git-update-cache --ignore-missing --refresh - - -################################################################ -git-write-blob - - git-write-blob - -Writes the contents of the named file (which can be outside of the work -tree) as a blob into the object database, and reports its object ID to its -standard output. This is used by git-merge-one-file-script to update the -cache without modifying files in the work tree. - - -################################################################ -git-write-tree - git-write-tree - -Creates a tree object using the current cache. - -The cache must be merged. - -Conceptually, git-write-tree sync()s the current directory cache contents -into a set of tree files. -In order to have that match what is actually in your directory right -now, you need to have done a "git-update-cache" phase before you did the -"git-write-tree". - - -################################################################ - -Output format from git-diff-cache, git-diff-tree and git-diff-files. - -These commands all compare two sets of things; what are -compared are different: - - git-diff-cache - - compares the and the files on the filesystem. - - git-diff-cache --cached - - compares the and the cache. - - git-diff-tree [-r] [...] - - compares the trees named by the two arguments. - - git-diff-files [...] - - compares the cache and the files on the filesystem. - -The following desription uses "old" and "new" to mean those -compared entities. - -For files in old but not in new (i.e. removed): -- \t \t \t - -For files not in old but in new (i.e. added): -+ \t \t \t - -For files that differ: -*-> \t \t -> \t - - is shown as all 0's if new is a file on the -filesystem and it is out of sync with the cache. Example: - - *100644->100644 blob 5be4a4.......->000000....... file.c - -################################################################ - -Generating patches - -When git-diff-cache, git-diff-tree, or git-diff-files are run with a -p -option, they do not produce the output described in "Output format from -git-diff-cache, git-diff-tree and git-diff-files" section. It instead -produces a patch file. - -The patch generation can be customized at two levels. This -customization also applies to git-diff-tree-helper. - -1. When the environment variable GIT_EXTERNAL_DIFF is not set, - these commands internally invoke diff like this: - - diff -L a/ -L a/ -pu - - For added files, /dev/null is used for . For removed - files, /dev/null is used for - - The diff formatting options can be customized via the - environment variable GIT_DIFF_OPTS. For example, if you - prefer context diff: - - GIT_DIFF_OPTS=-c git-diff-cache -p $(cat .git/HEAD) - - -2. When the environment variable GIT_EXTERNAL_DIFF is set, the - program named by it is called, instead of the diff invocation - described above. - - For a path that is added, removed, or modified, - GIT_EXTERNAL_DIFF is called with 7 parameters: - - path old-file old-hex old-mode new-file new-hex new-mode - - where - -file are files GIT_EXTERNAL_DIFF can use to read the - contents of , - -hex are the 40-hexdigit SHA1 hashes, - -mode are the octal representation of the file modes. - - The file parameters can point at the user's working file (e.g. new-file - in git-diff-files), /dev/null (e.g. old-file when a new file is added), - or a temporary file (e.g. old-file in the cache). GIT_EXTERNAL_DIFF - should not worry about unlinking the temporary file --- it is removed - when GIT_EXTERNAL_DIFF exits. - - For a path that is unmerged, GIT_EXTERNAL_DIFF is called with - 1 parameter, path. - -################################################################ - -Terminology: - see README for description -Each line contains terms used interchangeably - -object database, .git directory -directory cache, index -id, sha1, sha1-id, sha1 hash -type, tag -blob, blob object -tree, tree object -commit, commit object -parent -root object -changeset - - -git Environment Variables -AUTHOR_NAME -AUTHOR_EMAIL -AUTHOR_DATE -COMMIT_AUTHOR_NAME -COMMIT_AUTHOR_EMAIL -GIT_DIFF_OPTS -GIT_EXTERNAL_DIFF -GIT_INDEX_FILE -SHA1_FILE_DIRECTORY diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt new file mode 100644 index 00000000..1a99e85e --- /dev/null +++ b/Documentation/diff-format.txt @@ -0,0 +1,89 @@ +The output format from "git-diff-cache", "git-diff-tree" and +"git-diff-files" is very similar. + +These commands all compare two sets of things; what are +compared are different: + +git-diff-cache :: + compares the and the files on the filesystem. + +git-diff-cache --cached :: + compares the and the cache. + +git-diff-tree [-r] [...]:: + compares the trees named by the two arguments. + +git-diff-files [...]:: + compares the cache and the files on the filesystem. + +The following desription uses "old" and "new" to mean those +compared entities. + +For files in old but not in new (i.e. removed): + + - \t \t \t + +For files not in old but in new (i.e. added): + + + \t \t \t + +For files that differ: + + *-> \t \t -> \t + + is shown as all 0's if new is a file on the +filesystem and it is out of sync with the cache. Example: + + *100644->100644 blob 5be4a4.......->000000....... file.c + + +Generating patches with -p +-------------------------- + +When "git-diff-cache", "git-diff-tree", or "git-diff-files" are run +with a '-p' option, they do not produce the output described above +instead they produce a patch file. + +The patch generation can be customized at two levels. This +customization also applies to "git-diff-tree-helper". + +1. When the environment variable 'GIT_EXTERNAL_DIFF' is not set, + these commands internally invoke "diff" like this: + + diff -L a/ -L a/ -pu ++ +For added files, `/dev/null` is used for . For removed +files, `/dev/null` is used for ++ +The "diff" formatting options can be customized via the +environment variable 'GIT_DIFF_OPTS'. For example, if you +prefer context diff: + + GIT_DIFF_OPTS=-c git-diff-cache -p $(cat .git/HEAD) + + +2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the + program named by it is called, instead of the diff invocation + described above. ++ +For a path that is added, removed, or modified, +'GIT_EXTERNAL_DIFF' is called with 7 parameters: + + path old-file old-hex old-mode new-file new-hex new-mode ++ +where: + + -file:: are files GIT_EXTERNAL_DIFF can use to read the + contents of , + -hex:: are the 40-hexdigit SHA1 hashes, + -mode:: are the octal representation of the file modes. + ++ +The file parameters can point at the user's working file +(e.g. `new-file` in "git-diff-files"), `/dev/null` (e.g. `old-file` +when a new file is added), or a temporary file (e.g. `old-file` in the +cache). 'GIT_EXTERNAL_DIFF' should not worry about unlinking the +temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits. + +For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1 +parameter, . diff --git a/Documentation/git-apply-patch-script.txt b/Documentation/git-apply-patch-script.txt new file mode 100644 index 00000000..a6f860d4 --- /dev/null +++ b/Documentation/git-apply-patch-script.txt @@ -0,0 +1,32 @@ +git-apply-patch-script(1) +========================= +v0.1, May 2005 + +NAME +---- +git-apply-patch-script - Sample script to apply the diffs from git-diff-* + + +SYNOPSIS +-------- +'git-apply-patch-script' + +DESCRIPTION +----------- +This is a sample script to be used via the 'GIT_EXTERNAL_DIFF' +environment variable to apply the differences that the "git-diff-*" +family of commands report to the current work tree. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt new file mode 100644 index 00000000..48fb3776 --- /dev/null +++ b/Documentation/git-cat-file.txt @@ -0,0 +1,55 @@ +git-cat-file(1) +=============== +v0.1, May 2005 + +NAME +---- +git-cat-file - Provide content or type information for repository objects + + +SYNOPSIS +-------- +'git-cat-file' (-t | ) + +DESCRIPTION +----------- +Provides content or type of objects in the repository. The type +is required if '-t' is not being used to find the object type. + +OPTIONS +------- +:: + The sha1 identifier of the object. + +-t:: + Instead of the content, show the object type identified by + . + +:: + Typically this matches the real type of but asking + for a type that can trivially dereferenced from the given + is also permitted. An example is to ask for a + "tree" with being a commit object that contains it, + or to ask for a "blob" with being a tag object that + points at it. + +OUTPUT +------ +If '-t' is specified, one of the . + +Otherwise the raw (though uncompressed) contents of the will +be returned. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-check-files.txt b/Documentation/git-check-files.txt new file mode 100644 index 00000000..61460980 --- /dev/null +++ b/Documentation/git-check-files.txt @@ -0,0 +1,50 @@ +git-check-files(1) +================== +v0.1, May 2005 + +NAME +---- +git-check-files - Verify a list of files are up-to-date + + + +SYNOPSIS +-------- +'git-check-files' ... + +DESCRIPTION +----------- +Check that a list of files are up-to-date between the filesystem and +the cache. Used to verify a patch target before doing a patch. + +Files that do not exist on the filesystem are considered up-to-date +(whether or not they are in the cache). + +Emits an error message on failure: + +preparing to update existing file not in cache:: + exists but is not in the cache + +preparing to update file not uptodate in cache:: + on disk is not up-to-date with the cache + +Exits with a status code indicating success if all files are +up-to-date. + +See Also +-------- +link:git-update-cache.html[git-update-cache] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-checkout-cache.txt b/Documentation/git-checkout-cache.txt new file mode 100644 index 00000000..9d41626d --- /dev/null +++ b/Documentation/git-checkout-cache.txt @@ -0,0 +1,102 @@ +git-checkout-cache(1) +===================== +v0.1, May 2005 + +NAME +---- +git-checkout-cache - Copy files from the cache to the working directory + + +SYNOPSIS +-------- +'git-checkout-cache' [-q] [-a] [-f] [-n] [--prefix=] + [--] ... + +DESCRIPTION +----------- +Will copy all files listed from the cache to the working directory +(not overwriting existing files). + +OPTIONS +------- +-q:: + be quiet if files exist or are not in the cache + +-f:: + forces overwrite of existing files + +-a:: + checks out all files in the cache (will then continue to + process listed files). + +-n:: + Don't checkout new files, only refresh files already checked + out. + +--prefix=:: + When creating files, prepend (usually a directory + including a trailing /) + +--:: + Do not interpret any more arguments as options. + +Note that the order of the flags matters: + + git-checkout-cache -a -f file.c + +will first check out all files listed in the cache (but not overwrite +any old ones), and then force-checkout `file.c` a second time (ie that +one *will* overwrite any old contents with the same filename). + +Also, just doing "git-checkout-cache" does nothing. You probably meant +"git-checkout-cache -a". And if you want to force it, you want +"git-checkout-cache -f -a". + +Intuitiveness is not the goal here. Repeatability is. The reason for +the "no arguments means no work" thing is that from scripts you are +supposed to be able to do things like: + + find . -name '*.h' -print0 | xargs -0 git-checkout-cache -f -- + +which will force all existing `*.h` files to be replaced with their +cached copies. If an empty command line implied "all", then this would +force-refresh everything in the cache, which was not the point. + +To update and refresh only the files already checked out: + + git-checkout-cache -n -f -a && git-update-cache --ignore-missing --refresh + +Oh, and the "--" is just a good idea when you know the rest will be +filenames. Just so that you wouldn't have a filename of "-a" causing +problems (not possible in the above example, but get used to it in +scripting!). + +The prefix ability basically makes it trivial to use +git-checkout-cache as an "export as tree" function. Just read the +desired tree into the index, and do a + + git-checkout-cache --prefix=git-export-dir/ -a + +and git-checkout-cache will "export" the cache into the specified +directory. + +NOTE The final "/" is important. The exported name is literally just +prefixed with the specified string, so you can also do something like + + git-checkout-cache --prefix=.merged- Makefile + +to check out the currently cached copy of `Makefile` into the file +`.merged-Makefile` + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt new file mode 100644 index 00000000..c0dc1f46 --- /dev/null +++ b/Documentation/git-commit-tree.txt @@ -0,0 +1,88 @@ +git-commit-tree(1) +================== +v0.1, May 2005 + +NAME +---- +git-commit-tree - Creates a new commit object + + +SYNOPSIS +-------- +'git-commit-tree' [-p ]\ < changelog + +DESCRIPTION +----------- +Creates a new commit object based on the provided tree object and +emits the new commit object id on stdout. If no parent is given then +it is considered to be an initial tree. + +A commit object usually has 1 parent (a commit after a change) or up +to 16 parents. More than one parent represents a merge of branches +that led to them. + +While a tree represents a particular directory state of a working +directory, a commit represents that state in "time", and explains how +to get there. + +Normally a commit would identify 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 result to the file `.git/HEAD`, so that we can +always see what the last committed state was. + +OPTIONS +------- +:: + An existing tree object + +-p :: + Each '-p' indicates a the id of a parent commit object. + + +Commit Information +------------------ + +A commit encapsulates: + +- all parent object ids +- author name, email and date +- committer name and email and the commit time. + +If not provided, "git-commit-tree" uses your name, hostname and domain to +provide author and committer info. This can be overridden using the +following environment variables. + + GIT_AUTHOR_NAME + GIT_AUTHOR_EMAIL + GIT_AUTHOR_DATE + GIT_COMMITTER_NAME + GIT_COMMITTER_EMAIL + +(nb <,> and '\n's are stripped) + +A commit comment is read from stdin (max 999 chars). If a changelog +entry is not provided via '<' redirection, "git-commit-tree" will just wait +for one to be entered and terminated with ^D + +Diagnostics +----------- +You don't exist. Go away!:: + The passwd(5) gecos field couldn't be read + +See Also +-------- +link:git-write-tree.html[git-write-tree] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-convert-cache.txt b/Documentation/git-convert-cache.txt new file mode 100644 index 00000000..66d7fe78 --- /dev/null +++ b/Documentation/git-convert-cache.txt @@ -0,0 +1,30 @@ +git-convert-cache(1) +==================== +v0.1, May 2005 + +NAME +---- +git-convert-cache - Converts old-style GIT repository + + +SYNOPSIS +-------- +'git-convert-cache' + +DESCRIPTION +----------- +Converts old-style GIT repository to the latest format + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-diff-cache.txt b/Documentation/git-diff-cache.txt new file mode 100644 index 00000000..b54b8226 --- /dev/null +++ b/Documentation/git-diff-cache.txt @@ -0,0 +1,141 @@ +git-diff-cache(1) +================= +v0.1, May 2005 + +NAME +---- +git-diff-cache - Compares content and mode of blobs between the cache and repository + + +SYNOPSIS +-------- +'git-diff-cache' [-p] [-r] [-z] [-m] [--cached] + +DESCRIPTION +----------- +Compares the content and mode of the blobs found via a tree object +with the content of the current cache and, optionally ignoring the +stat state of the file on disk. + +OPTIONS +------- +:: + The id of a tree object to diff against. + +-p:: + Generate patch (see section on generating patches) + +-r:: + This flag does not mean anything. It is there only to match + "git-diff-tree". Unlike "git-diff-tree", "git-diff-cache" + always looks at all the subdirectories. + +-z:: + \0 line termination on output + +--cached:: + do not consider the on-disk file at all + +-m:: + By default, files recorded in the index but not checked + out are reported as deleted. This flag makes + "git-diff-cache" say that all non-checked-out files are up + to date. + +Output format +------------- +include::diff-format.txt[] + +Operating Modes +--------------- +You can choose whether you want to trust the index file entirely +(using the '--cached' flag) or ask the diff logic to show any files +that don't match the stat state as being "tentatively changed". Both +of these operations are very useful indeed. + +Cached Mode +----------- +If '--cached' is specified, it allows you to ask: + + show me the differences between HEAD and the current index + contents (the ones I'd write with a "git-write-tree") + +For example, let's say that you have worked on your index file, and are +ready to commit. You want to see eactly *what* you are going to commit is +without having to write a new tree object and compare it that way, and to +do that, you just do + + git-diff-cache --cached $(cat .git/HEAD) + +Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had +done an "git-update-cache" to make that effective in the index file. +"git-diff-files" wouldn't show anything at all, since the index file +matches my working directory. But doing a "git-diff-cache" does: + + torvalds@ppc970:~/git> git-diff-cache --cached $(cat .git/HEAD) + -100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c + +100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c + +You can trivially see that the above is a rename. + +In fact, "git-diff-cache --cached" *should* always be entirely equivalent to +actually doing a "git-write-tree" and comparing that. Except this one is much +nicer for the case where you just want to check where you are. + +So doing a "git-diff-cache --cached" is basically very useful when you are +asking yourself "what have I already marked for being committed, and +what's the difference to a previous tree". + +Non-cached Mode +--------------- +The "non-cached" mode takes a different approach, and is potentially +the more useful of the two in that what it does can't be emulated with +a "git-write-tree" + "git-diff-tree". Thus that's the default mode. +The non-cached version asks the question: + + show me the differences between HEAD and the currently checked out + tree - index contents _and_ files that aren't up-to-date + +which is obviously a very useful question too, since that tells you what +you *could* commit. Again, the output matches the "git-diff-tree -r" +output to a tee, but with a twist. + +The twist is that if some file doesn't match the cache, we don't have +a backing store thing for it, and we use the magic "all-zero" sha1 to +show that. So let's say that you have edited `kernel/sched.c`, but +have not actually done a "git-update-cache" on it yet - there is no +"object" associated with the new state, and you get: + + torvalds@ppc970:~/v2.6/linux> git-diff-cache $(cat .git/HEAD ) + *100644->100664 blob 7476bb......->000000...... kernel/sched.c + +ie it shows that the tree has changed, and that `kernel/sched.c` has is +not up-to-date and may contain new stuff. The all-zero sha1 means that to +get the real diff, you need to look at the object in the working directory +directly rather than do an object-to-object diff. + +NOTE! As with other commands of this type, "git-diff-cache" does not +actually look at the contents of the file at all. So maybe +`kernel/sched.c` hasn't actually changed, and it's just that you +touched it. In either case, it's a note that you need to +"git-upate-cache" it to make the cache be in sync. + +NOTE 2! You can have a mixture of files show up as "has been updated" +and "is still dirty in the working directory" together. You can always +tell which file is in which state, since the "has been updated" ones +show a valid sha1, and the "not in sync with the index" ones will +always have the special all-zero sha1. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt new file mode 100644 index 00000000..0ad2f895 --- /dev/null +++ b/Documentation/git-diff-files.txt @@ -0,0 +1,51 @@ +git-diff-files(1) +================= +v0.1, May 2005 + +NAME +---- +git-diff-files - Compares files in the working tree and the cache + + +SYNOPSIS +-------- +'git-diff-files' [-p] [-q] [-r] [-z] [...] + +DESCRIPTION +----------- +Compares the files in the working tree and the cache. When paths +are specified, compares only those named paths. Otherwise all +entries in the cache are compared. The output format is the +same as "git-diff-cache" and "git-diff-tree". + +OPTIONS +------- +-p:: + generate patch (see section on generating patches). + +-q:: + Remain silent even on nonexisting files + +-r:: + This flag does not mean anything. It is there only to match + git-diff-tree. Unlike git-diff-tree, git-diff-files always looks + at all the subdirectories. + + +Output format +------------- +include::diff-format.txt[] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-diff-tree-helper.txt b/Documentation/git-diff-tree-helper.txt new file mode 100644 index 00000000..58f27172 --- /dev/null +++ b/Documentation/git-diff-tree-helper.txt @@ -0,0 +1,49 @@ +git-diff-tree-helper(1) +======================= +v0.1, May 2005 + +NAME +---- +git-diff-tree-helper - Generates patch format output for git-diff-* + + +SYNOPSIS +-------- +'git-diff-tree-helper' [-z] [-R] + +DESCRIPTION +----------- +Reads output from "git-diff-cache", "git-diff-tree" and "git-diff-files" and +generates patch format output. + +OPTIONS +------- +-z:: + \0 line termination on input + +-R:: + Output diff in reverse. This is useful for displaying output from + "git-diff-cache" which always compares tree with cache or working + file. E.g. + + git-diff-cache | git-diff-tree-helper -R file.c ++ +would show a diff to bring the working file back to what is in the . + +See Also +-------- +The section on generating patches in link:git-diff-cache.html[git-diff-cache] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt new file mode 100644 index 00000000..ff7f25f3 --- /dev/null +++ b/Documentation/git-diff-tree.txt @@ -0,0 +1,126 @@ +git-diff-tree(1) +================ +v0.1, May 2005 + +NAME +---- +git-diff-tree - Compares the content and mode of blobs found via two tree objects + + +SYNOPSIS +-------- +'git-diff-tree' [-p] [-r] [-z] [--stdin] [-m] [-s] [-v] []\* + +DESCRIPTION +----------- +Compares the content and mode of the blobs found via two tree objects. + +Note that "git-diff-tree" can use the tree encapsulated in a commit object. + +OPTIONS +------- +:: + The id of a tree object. + +:: + If provided, the results are limited to a subset of files + matching one of these prefix strings. + ie file matches `/^||.../` + Note that pattern does not provide any wildcard or regexp + features. + +-p:: + generate patch (see section on generating patches). For + git-diff-tree, this flag implies '-r' as well. + +-r:: + recurse + +-z:: + \0 line termination on output + +--stdin:: + When '--stdin' is specified, the command does not take + arguments from the command line. Instead, it + reads either one or a pair of + separated with a single space from its standard input. ++ +When a single commit is given on one line of such input, it compares +the commit with its parents. The following flags further affects its +behaviour. This does not apply to the case where two +separated with a single space are given. + +-m:: + By default, "git-diff-tree --stdin" does not show + differences for merge commits. With this flag, it shows + differences to that commit from all of its parents. + +-s:: + By default, "git-diff-tree --stdin" shows differences, + either in machine-readable form (without '-p') or in patch + form (with '-p'). This output can be supressed. It is + only useful with '-v' flag. + +-v:: + This flag causes "git-diff-tree --stdin" to also show + the commit message before the differences. + + +Limiting Output +--------------- +If you're only interested in differences in a subset of files, for +example some architecture-specific files, you might do: + + git-diff-tree -r arch/ia64 include/asm-ia64 + +and it will only show you what changed in those two directories. + +Or if you are searching for what changed in just `kernel/sched.c`, just do + + git-diff-tree -r kernel/sched.c + +and it will ignore all differences to other files. + +The pattern is always the prefix, and is matched exactly. There are no +wildcards. Even stricter, it has to match complete path comonent. +I.e. "foo" does not pick up `foobar.h`. "foo" does match `foo/bar.h` +so it can be used to name subdirectories. + +An example of normal usage is: + + torvalds@ppc970:~/git> git-diff-tree 5319e4...... + *100664->100664 blob ac348b.......->a01513....... git-fsck-cache.c + +which tells you that the last commit changed just one file (it's from +this one: + + commit 3c6f7ca19ad4043e9e72fa94106f352897e651a8 + tree 5319e4d609cdd282069cc4dce33c1db559539b03 + parent b4e628ea30d5ab3606119d2ea5caeab141d38df7 + author Linus Torvalds Sat Apr 9 12:02:30 2005 + committer Linus Torvalds Sat Apr 9 12:02:30 2005 + + Make "git-fsck-cache" print out all the root commits it finds. + + Once I do the reference tracking, I'll also make it print out all the + HEAD commits it finds, which is even more interesting. + +in case you care). + +Output format +------------- +include::diff-format.txt[] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-export.txt b/Documentation/git-export.txt new file mode 100644 index 00000000..d2d0dc49 --- /dev/null +++ b/Documentation/git-export.txt @@ -0,0 +1,31 @@ +git-export(1) +============= +v0.1, May 2005 + +NAME +---- +git-export - Exports each commit and a diff against each of its parents + + +SYNOPSIS +-------- +'git-export' top [base] + +DESCRIPTION +----------- +Exports each commit and diff against each of its parents, between +top and base. If base is not specified it exports everything. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-fsck-cache.txt b/Documentation/git-fsck-cache.txt new file mode 100644 index 00000000..bcd3b0ad --- /dev/null +++ b/Documentation/git-fsck-cache.txt @@ -0,0 +1,122 @@ +git-fsck-cache(1) +================= +v0.1, May 2005 + +NAME +---- +git-fsck-cache - Verifies the connectivity and validity of the objects in the database + + +SYNOPSIS +-------- +'git-fsck-cache' [--tags] [--root] [[--unreachable] [--cache] \*] + +DESCRIPTION +----------- +Verifies the connectivity and validity of the objects in the database. + +OPTIONS +------- +:: + An object to treat as the head of an unreachability trace. + +--unreachable:: + Print out objects that exist but that aren't readable from any + of the specified head nodes. + +--root:: + Report root nodes. + +--tags:: + Report tags. + +--cache:: + Consider any object recorded in the cache also as a head node for + an unreachability trace. + +It tests SHA1 and general object sanity, and it does full tracking of +the resulting reachability and everything else. It prints out any +corruption it finds (missing or bad objects), and if you use the +'--unreachable' flag it will also print out objects that exist but +that aren't readable from any of the specified head nodes. + +So for example + + git-fsck-cache --unreachable $(cat .git/HEAD) + +or, for Cogito users: + + git-fsck-cache --unreachable $(cat .git/refs/heads/*) + +will do quite a _lot_ of verification on the tree. There are a few +extra validity tests to be added (make sure that tree objects are +sorted properly etc), but on the whole if "git-fsck-cache" is happy, you +do have a valid tree. + +Any corrupt objects you will have to find in backups or other archives +(ie you can just remove them and do an "rsync" with some other site in +the hopes that somebody else has the object you have corrupted). + +Of course, "valid tree" doesn't mean that it wasn't generated by some +evil person, and the end result might be crap. Git is a revision +tracking system, not a quality assurance system ;) + +Extracted Diagnostics +--------------------- + +expect dangling commits - potential heads - due to lack of head information:: + You haven't specified any nodes as heads so it won't be + possible to differentiate between un-parented commits and + root nodes. + +missing sha1 directory '':: + The directory holding the sha1 objects is missing. + +unreachable :: + The object , isn't actually referred to directly + or indirectly in any of the trees or commits seen. This can + mean that there's another root node that you're not specifying + or that the tree is corrupt. If you haven't missed a root node + then you might as well delete unreachable nodes since they + can't be used. + +missing :: + The object , is referred to but isn't present in + the database. + +dangling :: + The object , is present in the database but never + 'directly' used. A dangling commit could be a root node. + +warning: git-fsck-cache: tree has full pathnames in it:: + And it shouldn't... + +sha1 mismatch :: + The database has an object who's sha1 doesn't match the + database value. + This indicates a serious data integrity problem. + (note: this error occured during early git development when + the database format changed.) + +Environment Variables +--------------------- + +GIT_OBJECT_DIRECTORY:: + used to specify the object database root (usually .git/objects) + +GIT_INDEX_FILE:: + used to specify the cache + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-http-pull.txt b/Documentation/git-http-pull.txt new file mode 100644 index 00000000..59cd090a --- /dev/null +++ b/Documentation/git-http-pull.txt @@ -0,0 +1,39 @@ +git-http-pull(1) +================ +v0.1, May 2005 + +NAME +---- +git-http-pull - Downloads a remote GIT repository via HTTP + + +SYNOPSIS +-------- +'git-http-pull' [-c] [-t] [-a] [-v] commit-id url + +DESCRIPTION +----------- +Downloads a remote GIT repository via HTTP. + +-c:: + Get the commit objects. +-t:: + Get trees associated with the commit objects. +-a:: + Get all the objects. +-v:: + Report what is downloaded. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt new file mode 100644 index 00000000..99f96f7d --- /dev/null +++ b/Documentation/git-init-db.txt @@ -0,0 +1,40 @@ +git-init-db(1) +============== +v0.1, May 2005 + +NAME +---- +git-init-db - Creates an empty git object database + + +SYNOPSIS +-------- +'git-init-db' + +DESCRIPTION +----------- +This simply creates an empty git object database - basically a `.git` +directory and `.git/object/??/` directories. + +If the 'GIT_DIR' environment variable is set then it specifies a path +to use instead of `./.git` for the base of the repository. + +If the object storage directory is specified via the 'GIT_OBJECT_DIRECTORY' +environment variable then the sha1 directories are created underneath - +otherwise the default `.git/objects` directory is used. + +"git-init-db" won't hurt an existing repository. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-local-pull.txt b/Documentation/git-local-pull.txt new file mode 100644 index 00000000..53f5d396 --- /dev/null +++ b/Documentation/git-local-pull.txt @@ -0,0 +1,40 @@ +git-local-pull(1) +================= +v0.1, May 2005 + +NAME +---- +git-local-pull - Duplicates another GIT repository on a local system + + +SYNOPSIS +-------- +'git-local-pull' [-c] [-t] [-a] [-l] [-s] [-n] [-v] commit-id path + +DESCRIPTION +----------- +Duplicates another GIT repository on a local system. + +OPTIONS +------- +-c:: + Get the commit objects. +-t:: + Get trees associated with the commit objects. +-a:: + Get all the objects. +-v:: + Report what is downloaded. + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt new file mode 100644 index 00000000..14ca6953 --- /dev/null +++ b/Documentation/git-ls-files.txt @@ -0,0 +1,102 @@ +git-ls-files(1) +=============== +v0.1, May 2005 + +NAME +---- +git-ls-files - Information about files in the cache/working directory + + +SYNOPSIS +-------- +'git-ls-files' [-z] [-t] + (--[cached|deleted|others|ignored|stage|unmerged])\* + (-[c|d|o|i|s|u])\* + [-x |--exclude=] + [-X |--exclude-from=] + +DESCRIPTION +----------- +This merges the file listing in the directory cache index with the +actual working directory list, and shows different combinations of the +two. + +One or more of the options below may be used to determine the files +shown: + +OPTIONS +------- +-c|--cached:: + Show cached files in the output (default) + +-d|--deleted:: + Show deleted files in the output + +-o|--others:: + Show other files in the output + +-i|--ignored:: + Show ignored files in the output + Note the this also reverses any exclude list present. + +-s|--stage:: + Show stage files in the output + +-u|--unmerged:: + Show unmerged files in the output (forces --stage) + +-z:: + \0 line termination on output + +-x|--exclude=:: + Skips files matching pattern. + Note that pattern is a shell wildcard pattern. + +-X|--exclude-from=:: + exclude patterns are read from ; 1 per line. + Allows the use of the famous dontdiff file as follows to find + out about uncommitted files just as dontdiff is used with + the diff command: + git-ls-files --others --exclude-from=dontdiff + +-t:: + Identify the file status with the following tags (followed by + a space) at the start of each line: + H cached + M unmerged + R removed/deleted + ? other + +Output +------ +show files just outputs the filename unless '--stage' is specified in +which case it outputs: + + [ ] + +"git-ls-files --unmerged" and "git-ls-files --stage" can be used to examine +detailed information on unmerged paths. + +For an unmerged path, instead of recording a single mode/SHA1 pair, +the dircache records up to three such pairs; one from tree O in stage +1, A in stage 2, and B in stage 3. This information can be used by +the user (or Cogito) to see what should eventually be recorded at the +path. (see read-cache for more information on state) + +See Also +-------- +link:read-cache.html[read-cache] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt new file mode 100644 index 00000000..f6e15ad7 --- /dev/null +++ b/Documentation/git-ls-tree.txt @@ -0,0 +1,46 @@ +git-ls-tree(1) +============== +v0.1, May 2005 + +NAME +---- +git-ls-tree - Displays a tree object in human readable form + + +SYNOPSIS +-------- +'git-ls-tree' [-r] [-z] + +DESCRIPTION +----------- +Converts the tree object to a human readable (and script processable) +form. + +OPTIONS +------- +:: + Id of a tree. + +-r:: + recurse into sub-trees + +-z:: + \0 line termination on output + +Output Format +------------- + \t \t \t + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt new file mode 100644 index 00000000..1e27bf23 --- /dev/null +++ b/Documentation/git-merge-base.txt @@ -0,0 +1,34 @@ +git-merge-base(1) +================= +v0.1, May 2005 + +NAME +---- +git-merge-base - Finds as good a common ancestor as possible for a merge + + +SYNOPSIS +-------- +'git-merge-base' + +DESCRIPTION +----------- +"git-merge-base" finds as good a common ancestor as possible. Given a +selection of equally good common ancestors it should not be relied on +to decide in any particular way. + +The "git-merge-base" algorithm is still in flux - use the source... + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-merge-cache.txt b/Documentation/git-merge-cache.txt new file mode 100644 index 00000000..343607cf --- /dev/null +++ b/Documentation/git-merge-cache.txt @@ -0,0 +1,77 @@ +git-merge-cache(1) +================== +v0.1, May 2005 + +NAME +---- +git-merge-cache - Runs a merge for files needing merging + + +SYNOPSIS +-------- +'git-merge-cache' (-a | -- | \*) + +DESCRIPTION +----------- +This looks up the (s) in the cache and, if there are any merge +entries, passes the SHA1 hash for those files as arguments 1, 2, 3 (empty +argument if no file), and as argument 4. File modes for the three +files are passed as arguments 5, 6 and 7. + +OPTIONS +------- +--:: + Interpret all future arguments as filenames. + +-a:: + Run merge against all files in the cache that need merging. + +If "git-merge-cache" is called with multiple s (or -a) then it +processes them in turn only stopping if merge returns a non-zero exit +code. + +Typically this is run with the a script calling the merge command from +the RCS package. + +A sample script called "git-merge-one-file-script" is included in the +ditribution. + +ALERT ALERT ALERT! The git "merge object order" is different from the +RCS "merge" program merge object order. In the above ordering, the +original is first. But the argument order to the 3-way merge program +"merge" is to have the original in the middle. Don't ask me why. + +Examples: + + torvalds@ppc970:~/merge-test> git-merge-cache cat MM + This is MM from the original tree. # original + This is modified MM in the branch A. # merge1 + This is modified MM in the branch B. # merge2 + This is modified MM in the branch B. # current contents + +or + + torvalds@ppc970:~/merge-test> git-merge-cache cat AA MM + cat: : No such file or directory + This is added AA in the branch A. + This is added AA in the branch B. + This is added AA in the branch B. + fatal: merge program failed + +where the latter example shows how "git-merge-cache" will stop trying to +merge once anything has returned an error (ie "cat" returned an error +for the AA file, because it didn't exist in the original, and thus +"git-merge-cache" didn't even try to merge the MM thing). + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-merge-one-file-script.txt b/Documentation/git-merge-one-file-script.txt new file mode 100644 index 00000000..387601d7 --- /dev/null +++ b/Documentation/git-merge-one-file-script.txt @@ -0,0 +1,30 @@ +git-merge-one-file-script(1) +============================ +v0.1, May 2005 + +NAME +---- +git-merge-one-file-script - The standard helper program to use with "git-merge-cache" + + +SYNOPSIS +-------- +'git-merge-one-file-script' + +DESCRIPTION +----------- +This is the standard helper program to use with "git-merge-cache" +to resolve a merge after the trivial merge done with "git-read-tree -m". + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt new file mode 100644 index 00000000..708f4ef8 --- /dev/null +++ b/Documentation/git-mktag.txt @@ -0,0 +1,48 @@ +git-mktag(1) +============ +v0.1, May 2005 + +NAME +---- +git-mktag - Creates a tag object + + +SYNOPSIS +-------- +'git-mktag' < signature_file + +DESCRIPTION +----------- +Reads a tag contents on standard input and creates a tag object +that can also be used to sign other objects. + +The output is the new tag's identifier. + +Tag Format +---------- +A tag signature file has a very simple fixed format: three lines of + + object + type + tag + +followed by some 'optional' free-form signature that git itself +doesn't care about, but that can be verified with gpg or similar. + +The size of the full object is artificially limited to 8kB. (Just +because I'm a lazy bastard, and if you can't fit a signature in that +size, you're doing something wrong) + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-prune-script.txt b/Documentation/git-prune-script.txt new file mode 100644 index 00000000..537b7905 --- /dev/null +++ b/Documentation/git-prune-script.txt @@ -0,0 +1,32 @@ +git-prune-script(1) +=================== +v0.1, May 2005 + +NAME +---- +git-prune-script - Prunes all unreachable objects from the object database + + +SYNOPSIS +-------- +'git-prune-script' + +DESCRIPTION +----------- +This runs "git-fsck-cache --unreachable" program using the heads specified +on the command line (or `.git/refs/heads/\*` and `.git/refs/tags/\*` if none is +specified), and prunes all unreachable objects from the object database. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-pull-script.txt b/Documentation/git-pull-script.txt new file mode 100644 index 00000000..44fd09a9 --- /dev/null +++ b/Documentation/git-pull-script.txt @@ -0,0 +1,31 @@ +git-pull-script(1) +================== +v0.1, May 2005 + +NAME +---- +git-pull-script - Script used by Linus to pull and merge a remote repository + + +SYNOPSIS +-------- +'git-pull-script' + +DESCRIPTION +----------- +This script is used by Linus to pull from a remote repository and perform +a merge. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt new file mode 100644 index 00000000..cbde13db --- /dev/null +++ b/Documentation/git-read-tree.txt @@ -0,0 +1,152 @@ +git-read-tree(1) +================ +v0.1, May 2005 + +NAME +---- +git-read-tree - Reads tree information into the directory cache + + +SYNOPSIS +-------- +'git-read-tree' ( | -m [ ])" + +DESCRIPTION +----------- +Reads the tree information given by into the directory cache, +but does not actually *update* any of the files it "caches". (see: +git-checkout-cache) + +Optionally, it can merge a tree into the cache or perform a 3-way +merge. + +Trivial merges are done by "git-read-tree" itself. Only conflicting paths +will be in unmerged state when "git-read-tree" returns. + +OPTIONS +------- +-m:: + Perform a merge, not just a read + +:: + The id of the tree object(s) to be read/merged. + + +Merging +------- +If '-m' is specified, "git-read-tree" performs 2 kinds of merge, a single tree +merge if only 1 tree is given or a 3-way merge if 3 trees are +provided. + +Single Tree Merge +~~~~~~~~~~~~~~~~~ +If only 1 tree is specified, git-read-tree operates as if the user did not +specify '-m', except that if the original cache has an entry for a +given pathname; and the contents of the path matches with the tree +being read, the stat info from the cache is used. (In other words, the +cache's stat()s take precedence over the merged tree's) + +That means that if you do a "git-read-tree -m " followed by a +"git-checkout-cache -f -a", the "git-checkout-cache" only checks out +the stuff that really changed. + +This is used to avoid unnecessary false hits when "git-diff-files" is +run after git-read-tree. + +3-Way Merge +~~~~~~~~~~~ +Each "index" entry has two bits worth of "stage" state. stage 0 is the +normal one, and is the only one you'd see in any kind of normal use. + +However, when you do "git-read-tree" with three trees, the "stage" +starts out at 1. + +This means that you can do + + git-read-tree -m + +and you will end up with an index with all of the entries in +"stage1", all of the entries in "stage2" and all of the + entries in "stage3". + +Furthermore, "git-read-tree" has special-case logic that says: if you see +a file that matches in all respects in the following states, it +"collapses" back to "stage0": + + - stage 2 and 3 are the same; take one or the other (it makes no + difference - the same work has been done on stage 2 and 3) + + - stage 1 and stage 2 are the same and stage 3 is different; take + stage 3 (some work has been done on stage 3) + + - stage 1 and stage 3 are the same and stage 2 is different take + stage 2 (some work has been done on stage 2) + +The "git-write-tree" command refuses to write a nonsensical tree, and it +will complain about unmerged entries if it sees a single entry that is not +stage 0. + +Ok, this all sounds like a collection of totally nonsensical rules, +but it's actually exactly what you want in order to do a fast +merge. The different stages represent the "result tree" (stage 0, aka +"merged"), the original tree (stage 1, aka "orig"), and the two trees +you are trying to merge (stage 2 and 3 respectively). + +In fact, the way "git-read-tree" works, it's entirely agnostic about how +you assign the stages, and you could really assign them any which way, +and the above is just a suggested way to do it (except since +"git-write-tree" refuses to write anything but stage0 entries, it makes +sense to always consider stage 0 to be the "full merge" state). + +So what happens? Try it out. Select the original tree, and two trees +to merge, and look how it works: + +- if a file exists in identical format in all three trees, it will + automatically collapse to "merged" state by the new git-read-tree. + +- a file that has _any_ difference what-so-ever in the three trees + will stay as separate entries in the index. It's up to "script + policy" to determine how to remove the non-0 stages, and insert a + merged version. But since the index is always sorted, they're easy + to find: they'll be clustered together. + +- the index file saves and restores with all this information, so you + can merge things incrementally, but as long as it has entries in + stages 1/2/3 (ie "unmerged entries") you can't write the result. So + now the merge algorithm ends up being really simple: + + * you walk the index in order, and ignore all entries of stage 0, + since they've already been done. + + * if you find a "stage1", but no matching "stage2" or "stage3", you + know it's been removed from both trees (it only existed in the + original tree), and you remove that entry. + + * if you find a matching "stage2" and "stage3" tree, you remove one + of them, and turn the other into a "stage0" entry. Remove any + matching "stage1" entry if it exists too. .. all the normal + trivial rules .. + +Incidentally - it also means that you don't even have to have a +separate subdirectory for this. All the information literally is in +the index file, which is a temporary thing anyway. There is no need to +worry about what is in the working directory, since it is never shown +and never used. + +See Also +-------- +link:git-write-tree.html[git-write-tree]; link:git-ls-files.html[git-ls-files] + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-resolve-script.txt b/Documentation/git-resolve-script.txt new file mode 100644 index 00000000..8dd84a38 --- /dev/null +++ b/Documentation/git-resolve-script.txt @@ -0,0 +1,30 @@ +git-resolve-script(1) +===================== +v0.1, May 2005 + +NAME +---- +git-resolve-script - Script used to merge two trees + + +SYNOPSIS +-------- +'git-resolve-script' + +DESCRIPTION +----------- +This script is used by Linus to merge two trees. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt new file mode 100644 index 00000000..f2c5fa9f --- /dev/null +++ b/Documentation/git-rev-list.txt @@ -0,0 +1,32 @@ +git-rev-list(1) +=============== +v0.1, May 2005 + +NAME +---- +git-rev-list - Lists commit objects in reverse chronological order + + +SYNOPSIS +-------- +'git-rev-list' + +DESCRIPTION +----------- +Lists commit objects in reverse chronological order starting at the +given commit, taking ancestry relationship into account. This is +useful to produce human-readable log output. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-rev-tree.txt b/Documentation/git-rev-tree.txt new file mode 100644 index 00000000..2ec7ed07 --- /dev/null +++ b/Documentation/git-rev-tree.txt @@ -0,0 +1,88 @@ +git-rev-tree(1) +=============== +v0.1, May 2005 + +NAME +---- +git-rev-tree - Provides the revision tree for one or more commits + + +SYNOPSIS +-------- +'git-rev-tree' [--edges] [--cache ] [^] [[^]] + +DESCRIPTION +----------- +Provides the revision tree for one or more commits. + +OPTIONS +------- +--edges:: + Show edges (ie places where the marking changes between parent + and child) + +--cache :: + Use the specified file as a cache from a previous git-rev-list run + to speed things up. Note that this "cache" is totally different + concept from the directory index. Also this option is not + implemented yet. + +[^]:: + The commit id to trace (a leading caret means to ignore this + commit-id and below) + +Output +------ + + : [: ]\* + +:: + Date in 'seconds since epoch' + +:: + id of commit object + +:: + id of each parent commit object (>1 indicates a merge) + +:: + + The flags are read as a bitmask representing each commit + provided on the commandline. eg: given the command: + + $ git-rev-tree + + The output: + + :5 + + means that is reachable from (1) and (4) + +A revtree can get quite large. "git-rev-tree" will eventually allow +you to cache previous state so that you don't have to follow the whole +thing down. + +So the change difference between two commits is literally + + git-rev-tree [commit-id1] > commit1-revtree + git-rev-tree [commit-id2] > commit2-revtree + join -t : commit1-revtree commit2-revtree > common-revisions + +(this is also how to find the most common parent - you'd look at just +the head revisions - the ones that aren't referred to by other +revisions - in "common-revision", and figure out the best one. I +think.) + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-rpull.txt b/Documentation/git-rpull.txt new file mode 100644 index 00000000..1807fc57 --- /dev/null +++ b/Documentation/git-rpull.txt @@ -0,0 +1,43 @@ +git-rpull(1) +============ +v0.1, May 2005 + +NAME +---- +git-rpull - Pulls from a remote repository over ssh connection + + + +SYNOPSIS +-------- +'git-rpull' [-c] [-t] [-a] [-v] commit-id url + +DESCRIPTION +----------- +Pulls from a remote repository over ssh connection, invoking git-rpush on +the other end. + +OPTIONS +------- +-c:: + Get the commit objects. +-t:: + Get trees associated with the commit objects. +-a:: + Get all the objects. +-v:: + Report what is downloaded. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-rpush.txt b/Documentation/git-rpush.txt new file mode 100644 index 00000000..1c1cbab1 --- /dev/null +++ b/Documentation/git-rpush.txt @@ -0,0 +1,30 @@ +git-rpush(1) +============ +v0.1, May 2005 + +NAME +---- +git-rpush - Helper "server-side" program used by git-rpull + + +SYNOPSIS +-------- +'git-rpush' + +DESCRIPTION +----------- +Helper "server-side" program used by git-rpull. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-tag-script.txt b/Documentation/git-tag-script.txt new file mode 100644 index 00000000..daf350b5 --- /dev/null +++ b/Documentation/git-tag-script.txt @@ -0,0 +1,32 @@ +git-tag-script(1) +================= +v0.1, May 2005 + +NAME +---- +git-tag-script - An example script to create a tag object signed with GPG + + + +SYNOPSIS +-------- +'git-tag-script' + +DESCRIPTION +----------- +This is an example script that uses "git-mktag" to create a tag object +signed with GPG. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt new file mode 100644 index 00000000..7870e92a --- /dev/null +++ b/Documentation/git-tar-tree.txt @@ -0,0 +1,32 @@ +git-tar-tree(1) +=============== +v0.1, May 2005 + +NAME +---- +git-tar-tree - Creates a tar archive of the files in the named tree + + +SYNOPSIS +-------- +'git-tar-tree' [ ] + +DESCRIPTION +----------- +Creates a tar archive containing the tree structure for the named tree. +When is specified it is added as a leading path as the files in the +generated tar archive. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.txt new file mode 100644 index 00000000..2f2130d5 --- /dev/null +++ b/Documentation/git-unpack-file.txt @@ -0,0 +1,37 @@ +git-unpack-file(1) +================== +v0.1, May 2005 + +NAME +---- +git-unpack-file - Creates a temporary file with a blob's contents + + + +SYNOPSIS +-------- +'git-unpack-file' + +DESCRIPTION +----------- +Creates a file holding the contents of the blob specified by sha1. It +returns the name of the temporary file in the following format: + .merge_file_XXXXX + +OPTIONS +------- +:: + Must be a blob id + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-update-cache.txt b/Documentation/git-update-cache.txt new file mode 100644 index 00000000..604411d6 --- /dev/null +++ b/Documentation/git-update-cache.txt @@ -0,0 +1,108 @@ +git-update-cache(1) +=================== +v0.1, May 2005 + +NAME +---- +git-update-cache - Modifies the index or directory cache + + +SYNOPSIS +-------- +'git-update-cache' + [--add] [--remove] [--refresh] [--replace] + [--ignore-missing] + [--force-remove ] + [--cacheinfo ]\* + [--] []\* + +DESCRIPTION +----------- +Modifies the index or directory cache. Each file mentioned is updated +into the cache and any 'unmerged' or 'needs updating' state is +cleared. + +The way "git-update-cache" handles files it is told about can be modified +using the various options: + +OPTIONS +------- +--add:: + If a specified file isn't in the cache already then it's + added. + Default behaviour is to ignore new files. + +--remove:: + If a specified file is in the cache but is missing then it's + removed. + Default behaviour is to ignore removed file. + +--refresh:: + Looks at the current cache and checks to see if merges or + updates are needed by checking stat() information. + +--ignore-missing:: + Ignores missing files during a --refresh + +--cacheinfo :: + Directly insert the specified info into the cache. + +--force-remove:: + Remove the file from the index even when the working directory + still has such a file. + +--replace:: + By default, when a file `path` exists in the index, + git-update-cache refuses an attempt to add `path/file`. + Similarly if a file `path/file` exists, a file `path` + cannot be added. With --replace flag, existing entries + that conflicts with the entry being added are + automatically removed with warning messages. + +--:: + Do not interpret any more arguments as options. + +:: + Files to act on. + Note that files begining with '.' are discarded. This includes + `./file` and `dir/./file`. If you don't want this, then use + cleaner names. + The same applies to directories ending '/' and paths with '//' + +Using --refresh +--------------- +'--refresh' does not calculate a new sha1 file or bring the cache +up-to-date for mode/content changes. But what it *does* do is to +"re-match" the stat information of a file with the cache, so that you +can refresh the cache for a file that hasn't been changed but where +the stat entry is out of date. + +For example, you'd want to do this after doing a "git-read-tree", to link +up the stat cache details with the proper files. + +Using --cacheinfo +----------------- +'--cacheinfo' is used to register a file that is not in the current +working directory. This is useful for minimum-checkout merging. + +To pretend you have a file with mode and sha1 at path, say: + + $ git-update-cache --cacheinfo mode sha1 path + +To update and refresh only the files already checked out: + + git-checkout-cache -n -f -a && git-update-cache --ignore-missing --refresh + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-write-blob.txt b/Documentation/git-write-blob.txt new file mode 100644 index 00000000..22d75556 --- /dev/null +++ b/Documentation/git-write-blob.txt @@ -0,0 +1,33 @@ +git-write-blob(1) +================= +v0.1, May 2005 + +NAME +---- +git-write-blob - Creates a blob from a file + + +SYNOPSIS +-------- +'git-write-blob' + +DESCRIPTION +----------- +Writes the contents of the named file (which can be outside of the work +tree) as a blob into the object database, and reports its object ID to its +standard output. This is used by "git-merge-one-file-script" to update the +cache without modifying files in the work tree. + + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt new file mode 100644 index 00000000..458d97ac --- /dev/null +++ b/Documentation/git-write-tree.txt @@ -0,0 +1,52 @@ +git-write-tree(1) +================= +v0.1, May 2005 + +NAME +---- +git-write-tree - Creates a tree from the current cache + + +SYNOPSIS +-------- +'git-write-tree' + +DESCRIPTION +----------- +Creates a tree object using the current cache. + +The cache must be merged. + +Conceptually, "git-write-tree" sync()s the current directory cache contents +into a set of tree files. +In order to have that match what is actually in your directory right +now, you need to have done a "git-update-cache" phase before you did the +"git-write-tree". + + + + +//////////////////////////////////////////////////////////////// + +Producing man pages and html + +To create a set of html pages run: + perl split-docs.pl -html < core-git.txt + +To create a set of man pages run: + perl split-docs.pl -man < core-git.txt + + +//////////////////////////////////////////////////////////////// +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git.txt b/Documentation/git.txt new file mode 100644 index 00000000..a02ed6f4 --- /dev/null +++ b/Documentation/git.txt @@ -0,0 +1,309 @@ +git(1) +====== +v0.1, May 2005 + +NAME +---- +git - the stupid content tracker + + +SYNOPSIS +-------- +'git-' + +DESCRIPTION +----------- + +This is reference information for the core git commands. + +The link:README[] contains much useful definition and clarification +info - read that first. And of the commands, I suggest reading +'git-update-cache' and 'git-read-tree' first - I wish I had! + +David Greaves +08/05/05 + +Updated by Junio C Hamano on 2005-05-05 to +reflect recent changes. + +Commands Overview +----------------- +The git commands can helpfully be split into those that manipulate +the repository, the cache and the working fileset and those that +interrogate and compare them. + +There are also some ancilliary programs that can be viewed as useful +aids for using the core commands but which are unlikely to be used by +SCMs layered over git. + +Manipulation commands +~~~~~~~~~~~~~~~~~~~~~ +link:git-checkout-cache.html[git-checkout-cache]:: + Copy files from the cache to the working directory + +link:git-commit-tree.html[git-commit-tree]:: + Creates a new commit object + +link:git-init-db.html[git-init-db]:: + Creates an empty git object database + +link:git-merge-base.html[git-merge-base]:: + Finds as good a common ancestor as possible for a merge + +link:git-mktag.html[git-mktag]:: + Creates a tag object + +link:git-read-tree.html[git-read-tree]:: + Reads tree information into the directory cache + +link:git-update-cache.html[git-update-cache]:: + Modifies the index or directory cache + +link:git-write-blob.html[git-write-blob]:: + Creates a blob from a file + +link:git-write-tree.html[git-write-tree]:: + Creates a tree from the current cache + +Interrogation commands +~~~~~~~~~~~~~~~~~~~~~~ +link:git-cat-file.html[git-cat-file]:: + Provide content or type information for repository objects + +link:git-check-files.html[git-check-files]:: + Verify a list of files are up-to-date + +link:git-diff-cache.html[git-diff-cache]:: + Compares content and mode of blobs between the cache and repository + +link:git-diff-files.html[git-diff-files]:: + Compares files in the working tree and the cache + +link:git-diff-tree.html[git-diff-tree]:: + Compares the content and mode of blobs found via two tree objects + +link:git-export.html[git-export]:: + Exports each commit and a diff against each of its parents + +link:git-fsck-cache.html[git-fsck-cache]:: + Verifies the connectivity and validity of the objects in the database + +link:git-ls-files.html[git-ls-files]:: + Information about files in the cache/working directory + +link:git-ls-tree.html[git-ls-tree]:: + Displays a tree object in human readable form + +link:git-merge-cache.html[git-merge-cache]:: + Runs a merge for files needing merging + +link:git-rev-list.html[git-rev-list]:: + Lists commit objects in reverse chronological order + +link:git-rev-tree.html[git-rev-tree]:: + Provides the revision tree for one or more commits + +link:git-tar-tree.html[git-tar-tree]:: + Creates a tar archive of the files in the named tree + +link:git-unpack-file.html[git-unpack-file]:: + Creates a temporary file with a blob's contents + +The interrogate commands may create files - and you can force them to +touch the working file set - but in general they don't + + +Ancilliary Commands +------------------- +Manipulators: + +link:git-apply-patch-script.html[git-apply-patch-script]:: + Sample script to apply the diffs from git-diff-* + +link:git-convert-cache.html[git-convert-cache]:: + Converts old-style GIT repository + +link:git-http-pull.html[git-http-pull]:: + Downloads a remote GIT repository via HTTP + +link:git-local-pull.html[git-local-pull]:: + Duplicates another GIT repository on a local system + +link:git-merge-one-file-script.html[git-merge-one-file-script]:: + The standard helper program to use with "git-merge-cache" + +link:git-pull-script.html[git-pull-script]:: + Script used by Linus to pull and merge a remote repository + +link:git-prune-script.html[git-prune-script]:: + Prunes all unreachable objects from the object database + +link:git-resolve-script.html[git-resolve-script]:: + Script used to merge two trees + +link:git-tag-script.html[git-tag-script]:: + An example script to create a tag object signed with GPG + +link:git-rpull.html[git-rpull]:: + Pulls from a remote repository over ssh connection + +Interogators: + +link:git-diff-tree-helper.html[git-diff-tree-helper]:: + Generates patch format output for git-diff-* + +link:git-rpush.html[git-rpush]:: + Helper "server-side" program used by git-rpull + + + +Terminology +----------- +see README for description + +Identifier terminology +---------------------- +:: + Indicates any object sha1 identifier + +:: + Indicates a blob object sha1 identifier + +:: + Indicates a tree object sha1 identifier + +:: + Indicates a commit object sha1 identifier + +:: + Indicates a tree, commit or tag object sha1 identifier. + A command that takes a argument ultimately + wants to operate on a object but automatically + dereferences and that points at a + . + +:: + Indicates that an object type is required. + Currently one of: blob/tree/commit/tag + +:: + Indicates a filename - always relative to the root of + the tree structure GIT_INDEX_FILE describes. + +Symbolic Identifiers +-------------------- +Any git comand accepting any can also use the following symbolic notation: + +HEAD:: + indicates the head of the repository (ie the contents of `$GIT_DIR/HEAD`) +:: + a valid tag 'name'+ + (ie the contents of `$GIT_DIR/refs/tags/`) +:: + a valid head 'name'+ + (ie the contents of `$GIT_DIR/refs/heads/`) +:: + a valid snapshot 'name'+ + (ie the contents of `$GIT_DIR/refs/snap/`) + + +File/Directory Structure +------------------------ +The git-core manipulates the following areas in the directory: + + .git/ The base (overridden with $GIT_DIR) + objects/ The object base (overridden with $GIT_OBJECT_DIRECTORY) + ??/ 'First 2 chars of object' directories + +It can interrogate (but never updates) the following areas: + + refs/ Directories containing symbolic names for objects + (each file contains the hex SHA1 + newline) + heads/ Commits which are heads of various sorts + tags/ Tags, by the tag name (or some local renaming of it) + snap/ ???? + ... Everything else isn't shared + HEAD Symlink to refs/heads/ + +Higher level SCMs may provide and manage additional information in the +GIT_DIR. + +Terminology +----------- +Each line contains terms used interchangeably + + object database, .git directory + directory cache, index + id, sha1, sha1-id, sha1 hash + type, tag + blob, blob object + tree, tree object + commit, commit object + parent + root object + changeset + + +Environment Variables +--------------------- +Various git commands use the following environment variables: + +The git Repository +~~~~~~~~~~~~~~~~~~ +These environment variables apply to 'all' core git commands. Nb: it +is worth noting that they may be used/overridden by SCMS sitting above +git so take care if using Cogito etc + +'GIT_INDEX_FILE':: + This environment allows the specification of an alternate + cache/index file. If not specified, the default of + `$GIT_DIR/index` is used. + +'GIT_OBJECT_DIRECTORY':: + If the object storage directory is specified via this + environment variable then the sha1 directories are created + underneath - otherwise the default `$GIT_DIR/objects` + directory is used. + +'GIT_ALTERNATE_OBJECT_DIRECTORIES':: + Due to the immutable nature of git objects, old objects can be + archived into shared, read-only directories. This variable + specifies a ":" seperated list of git object directories which + can be used to search for git objects. New objects will not be + written to these directories. + +'GIT_DIR':: + If the 'GIT_DIR' environment variable is set then it specifies + a path to use instead of `./.git` for the base of the + repository. + +git Commits +~~~~~~~~~~~ +'GIT_AUTHOR_NAME':: +'GIT_AUTHOR_EMAIL':: +'GIT_AUTHOR_DATE':: +'GIT_COMMITTER_NAME':: +'GIT_COMMITTER_EMAIL':: + see link:git-commit-tree.html[git-commit-tree] + +git Diffs +~~~~~~~~~ +GIT_DIFF_OPTS:: +GIT_EXTERNAL_DIFF:: + see the "generating patches" section in : + link:git-diff-cache.html[git-diff-cache]; + link:git-diff-files.html[git-diff-files]; + link:git-diff-tree.html[git-diff-tree] + +Author +------ +Written by Linus Torvalds + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Makefile b/Makefile index a8d41757..6afcb3e8 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,16 @@ # BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely randomly # break unless your underlying filesystem supports those sub-second times # (my ext3 doesn't). -CFLAGS=-g -O2 -Wall +COPTS=-O2 +CFLAGS=-g $(COPTS) -Wall + +prefix=$(HOME) +bin=$(prefix)/bin +# dest= CC=gcc AR=ar +INSTALL=install SCRIPTS=git-apply-patch-script git-merge-one-file-script git-prune-script \ git-pull-script git-tag-script git-resolve-script @@ -21,12 +27,13 @@ PROG= git-update-cache git-diff-files git-init-db git-write-tree \ git-check-files git-ls-tree git-merge-base git-merge-cache \ git-unpack-file git-export git-diff-cache git-convert-cache \ git-http-pull git-rpush git-rpull git-rev-list git-mktag \ - git-diff-tree-helper git-tar-tree git-local-pull git-write-blob + git-diff-tree-helper git-tar-tree git-local-pull git-write-blob \ + git-get-tar-commit-id all: $(PROG) install: $(PROG) $(SCRIPTS) - install $(PROG) $(SCRIPTS) $(HOME)/bin/ + $(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bin) LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \ tag.o date.o @@ -39,6 +46,8 @@ LIB_OBJS += strbuf.o LIB_H += diff.h LIB_OBJS += diff.o +LIB_OBJS += gitenv.o + LIBS = $(LIB_FILE) LIBS += -lz @@ -51,7 +60,7 @@ ifdef PPC_SHA1 LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o else SHA1_HEADER= - LIBS += -lssl + LIBS += -lcrypto endif endif @@ -109,6 +118,7 @@ sha1_file.o: $(LIB_H) usage.o: $(LIB_H) diff.o: $(LIB_H) strbuf.o: $(LIB_H) +gitenv.o: $(LIB_H) clean: rm -f *.o mozilla-sha1/*.o ppc/*.o $(PROG) $(LIB_FILE) diff --git a/README b/README index d4fa56f7..0cccfe86 100644 --- a/README +++ b/README @@ -24,7 +24,7 @@ There are two object abstractions: the "object database", and the - The Object Database (SHA1_FILE_DIRECTORY) + The Object Database (GIT_OBJECT_DIRECTORY) The object database is literally just a content-addressable collection diff --git a/cache.h b/cache.h index f8329aed..ff229ee5 100644 --- a/cache.h +++ b/cache.h @@ -31,6 +31,13 @@ #endif /* + * Environment variables transition. + * We accept older names for now but warn. + */ +extern char *gitenv_bc(const char *); +#define gitenv(e) (getenv(e) ? : gitenv_bc(e)) + +/* * Basic data structures for the directory cache * * NOTE NOTE NOTE! This is all in the native CPU byte format. It's @@ -99,15 +106,15 @@ static inline unsigned int create_ce_mode(unsigned int mode) extern struct cache_entry **active_cache; extern unsigned int active_nr, active_alloc, active_cache_changed; -#define DB_ENVIRONMENT "SHA1_FILE_DIRECTORY" -#define DEFAULT_DB_ENVIRONMENT ".git/objects" - -#define get_object_directory() (getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT) - +#define GIT_DIR_ENVIRONMENT "GIT_DIR" +#define DEFAULT_GIT_DIR_ENVIRONMENT ".git" +#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY" #define INDEX_ENVIRONMENT "GIT_INDEX_FILE" -#define DEFAULT_INDEX_ENVIRONMENT ".git/index" -#define get_index_file() (getenv(INDEX_ENVIRONMENT) ? : DEFAULT_INDEX_ENVIRONMENT) +extern char *get_object_directory(void); +extern char *get_index_file(void); + +#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" #define alloc_nr(x) (((x)+16)*3/2) @@ -115,7 +122,9 @@ extern unsigned int active_nr, active_alloc, active_cache_changed; extern int read_cache(void); extern int write_cache(int newfd, struct cache_entry **cache, int entries); extern int cache_name_pos(const char *name, int namelen); -extern int add_cache_entry(struct cache_entry *ce, int ok_to_add); +#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */ +#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ +extern int add_cache_entry(struct cache_entry *ce, int option); extern int remove_entry_at(int pos); extern int remove_file_from_cache(char *path); extern int same_name(struct cache_entry *a, struct cache_entry *b); diff --git a/checkout-cache.c b/checkout-cache.c index 244ebd12..64ce9214 100644 --- a/checkout-cache.c +++ b/checkout-cache.c @@ -48,6 +48,7 @@ static void create_directories(const char *path) buf[len] = 0; mkdir(buf, 0755); } + free(buf); } static int create_file(const char *path, unsigned int mode) diff --git a/commit-tree.c b/commit-tree.c index cfd6730f..b8dd36f0 100644 --- a/commit-tree.c +++ b/commit-tree.c @@ -146,11 +146,11 @@ int main(int argc, char **argv) datestamp(realdate, sizeof(realdate)); strcpy(date, realdate); - commitgecos = getenv("COMMIT_AUTHOR_NAME") ? : realgecos; - commitemail = getenv("COMMIT_AUTHOR_EMAIL") ? : realemail; - gecos = getenv("AUTHOR_NAME") ? : realgecos; - email = getenv("AUTHOR_EMAIL") ? : realemail; - audate = getenv("AUTHOR_DATE"); + commitgecos = gitenv("GIT_COMMITTER_NAME") ? : realgecos; + commitemail = gitenv("GIT_COMMITTER_EMAIL") ? : realemail; + gecos = gitenv("GIT_AUTHOR_NAME") ? : realgecos; + email = gitenv("GIT_AUTHOR_EMAIL") ? : realemail; + audate = gitenv("GIT_AUTHOR_DATE"); if (audate) parse_date(audate, date, sizeof(date)); diff --git a/diff-cache.c b/diff-cache.c index 7e87d28f..84527190 100644 --- a/diff-cache.c +++ b/diff-cache.c @@ -165,7 +165,7 @@ static void mark_merge_entries(void) } static char *diff_cache_usage = -"diff-cache [-r] [-z] [-p] [-i] [--cached] "; +"git-diff-cache [-p] [-r] [-z] [-m] [--cached] "; int main(int argc, char **argv) { diff --git a/diff-tree-helper.c b/diff-tree-helper.c index a6832832..51bb658b 100644 --- a/diff-tree-helper.c +++ b/diff-tree-helper.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2005 Junio C Hamano */ +#include #include "cache.h" #include "strbuf.h" #include "diff.h" diff --git a/diff.c b/diff.c index 95488cdd..32309971 100644 --- a/diff.c +++ b/diff.c @@ -4,14 +4,15 @@ #include #include #include +#include #include "cache.h" #include "diff.h" -static char *diff_opts = "-pu"; +static const char *diff_opts = "-pu"; static const char *external_diff(void) { - static char *external_diff_cmd = NULL; + static const char *external_diff_cmd = NULL; static int done_preparing = 0; if (done_preparing) @@ -25,11 +26,11 @@ static const char *external_diff(void) * * GIT_DIFF_OPTS="-c"; */ - if (getenv("GIT_EXTERNAL_DIFF")) - external_diff_cmd = getenv("GIT_EXTERNAL_DIFF"); + if (gitenv("GIT_EXTERNAL_DIFF")) + external_diff_cmd = gitenv("GIT_EXTERNAL_DIFF"); /* In case external diff fails... */ - diff_opts = getenv("GIT_DIFF_OPTS") ? : diff_opts; + diff_opts = gitenv("GIT_DIFF_OPTS") ? : diff_opts; done_preparing = 1; return external_diff_cmd; diff --git a/fsck-cache.c b/fsck-cache.c index abdec92f..a00702b7 100644 --- a/fsck-cache.c +++ b/fsck-cache.c @@ -62,6 +62,9 @@ static void check_connectivity(void) * So a directory called "a" is ordered _after_ a file * called "a.c", because "a/" sorts after "a.c". */ +#define TREE_UNORDERED (-1) +#define TREE_HAS_DUPS (-2) + static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) { int len1 = strlen(a->name); @@ -74,7 +77,7 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) if (cmp < 0) return 0; if (cmp > 0) - return -1; + return TREE_UNORDERED; /* * Ok, the first characters are the same. @@ -83,11 +86,18 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) */ c1 = a->name[len]; c2 = b->name[len]; + if (!c1 && !c2) + /* + * git-write-tree used to write out a nonsense tree that has + * entries with the same name, one blob and one tree. Make + * sure we do not have duplicate entries. + */ + return TREE_HAS_DUPS; if (!c1 && a->directory) c1 = '/'; if (!c2 && b->directory) c2 = '/'; - return c1 < c2 ? 0 : -1; + return c1 < c2 ? 0 : TREE_UNORDERED; } static int fsck_tree(struct tree *item) @@ -123,10 +133,18 @@ static int fsck_tree(struct tree *item) } if (last) { - if (verify_ordered(last, entry) < 0) { + switch (verify_ordered(last, entry)) { + case TREE_UNORDERED: fprintf(stderr, "tree %s not ordered\n", sha1_to_hex(item->object.sha1)); return -1; + case TREE_HAS_DUPS: + fprintf(stderr, "tree %s has duplicate entries for '%s'\n", + sha1_to_hex(item->object.sha1), + entry->name); + return -1; + default: + break; } } @@ -306,7 +324,7 @@ int main(int argc, char **argv) usage("fsck-cache [--tags] [[--unreachable] [--cache] *]"); } - sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT; + sha1_dir = get_object_directory(); for (i = 0; i < 256; i++) { static char dir[4096]; sprintf(dir, "%s/%02x", sha1_dir, i); diff --git a/git-apply-patch-script b/git-apply-patch-script index 13ec1c44..0849a3e6 100755 --- a/git-apply-patch-script +++ b/git-apply-patch-script @@ -8,7 +8,7 @@ # case "$#" in -2) +1) echo >&2 "cannot handle unmerged diff on path $1." exit 1 ;; esac diff --git a/git-merge-one-file-script b/git-merge-one-file-script index 3fb43ccb..3e128c66 100755 --- a/git-merge-one-file-script +++ b/git-merge-one-file-script @@ -52,9 +52,9 @@ case "${1:-.}${2:-.}${3:-.}" in # "$1$2$3") echo "Auto-merging $4." - orig=$(git-unpack-file $1) - src1=$(git-unpack-file $2) - src2=$(git-unpack-file $3) + orig=`git-unpack-file $1` + src1=`git-unpack-file $2` + src2=`git-unpack-file $3` merge "$src2" "$orig" "$src1" ret=$? if [ "$6" != "$7" ]; then @@ -64,7 +64,7 @@ case "${1:-.}${2:-.}${3:-.}" in echo "ERROR: Leaving conflict merge in $src2." exit 1 fi - sha1=$(git-write-blob "$src2") || { + sha1=`git-write-blob "$src2"` || { echo "ERROR: Leaving conflict merge in $src2." } exec git-update-cache --add --cacheinfo "$6" $sha1 "$4" ;; diff --git a/git-prune-script b/git-prune-script index 9ba89a5b..1a97ccc9 100755 --- a/git-prune-script +++ b/git-prune-script @@ -11,6 +11,9 @@ do shift; done +: ${GIT_DIR=.git} +: ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} + # Defaulting to include .git/refs/*/* may be debatable from the # purist POV but power users can always give explicit parameters # to the script anyway. @@ -19,7 +22,8 @@ case "$#" in 0) x_40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' x_40="$x_40$x_40$x_40$x_40$x_40$x_40$x_40$x_40" - set x $(sed -ne "/^$x_40\$/p" .git/HEAD .git/refs/*/* 2>/dev/null) + set x $(sed -ne "/^$x_40\$/p" \ + "$GIT_DIR"/HEAD "$GIT_DIR"/refs/*/* /dev/null 2>/dev/null) shift ;; esac @@ -28,9 +32,7 @@ sed -ne '/unreachable /{ s/unreachable [^ ][^ ]* // s|\(..\)|\1/|p }' | { - case "$SHA1_FILE_DIRECTORY" in - '') cd .git/objects/ ;; - *) cd "$SHA1_FILE_DIRECTORY" ;; - esac || exit + cd "$GIT_OBJECT_DIRECTORY" || exit xargs -r $dryrun rm -f } + diff --git a/git-pull-script b/git-pull-script index 78d2f3df..bd892c7b 100755 --- a/git-pull-script +++ b/git-pull-script @@ -3,6 +3,9 @@ merge_repo=$1 merge_name=${2:-HEAD} +: ${GIT_DIR=.git} +: ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} + download_one () { # remote_path="$1" local_file="$2" case "$1" in @@ -25,16 +28,19 @@ download_objects () { git-local-pull -l -a "$2" "$1/" ;; *) - rsync -avz --ignore-existing "$1/objects/." \ - ${SHA_FILE_DIRECTORY:-.git/objects}/. + rsync -avz --ignore-existing \ + "$1/objects/." "$GIT_OBJECT_DIRECTORY"/. ;; esac } echo "Getting remote $merge_name" -download_one "$merge_repo/$merge_name" .git/MERGE_HEAD +download_one "$merge_repo/$merge_name" "$GIT_DIR"/MERGE_HEAD echo "Getting object database" -download_objects "$merge_repo" "$(cat .git/MERGE_HEAD)" +download_objects "$merge_repo" "$(cat "$GIT_DIR"/MERGE_HEAD)" -git-resolve-script "$(cat .git/HEAD)" "$(cat .git/MERGE_HEAD)" "$merge_repo" +git-resolve-script \ + "$(cat "$GIT_DIR"/HEAD)" \ + "$(cat "$GIT_DIR"/MERGE_HEAD)" \ + "$merge_repo" diff --git a/git-resolve-script b/git-resolve-script index c2f7a6e2..ec646fbb 100644 --- a/git-resolve-script +++ b/git-resolve-script @@ -1,14 +1,19 @@ #!/bin/sh # +# Copyright (c) 2005 Linus Torvalds +# # Resolve two trees. # head="$1" merge="$2" merge_repo="$3" -rm -f .git/MERGE_HEAD .git/ORIG_HEAD -echo $head > .git/ORIG_HEAD -echo $merge > .git/MERGE_HEAD +: ${GIT_DIR=.git} +: ${GIT_OBJECT_DIRECTORY="${SHA1_FILE_DIRECTORY-"$GIT_DIR/objects"}"} + +rm -f "$GIT_DIR"/MERGE_HEAD "$GIT_DIR"/ORIG_HEAD +echo $head > "$GIT_DIR"/ORIG_HEAD +echo $merge > "$GIT_DIR"/MERGE_HEAD # # The remote name is just used for the message, @@ -35,7 +40,7 @@ if [ "$common" == "$head" ]; then echo "Kill me within 3 seconds.." sleep 3 git-read-tree -m $merge && git-checkout-cache -f -a && git-update-cache --refresh - echo $merge > .git/HEAD + echo $merge > "$GIT_DIR"/HEAD git-diff-tree -p ORIG_HEAD HEAD | diffstat -p1 exit 0 fi @@ -51,6 +56,6 @@ if [ $? -ne 0 ]; then fi result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree -p $head -p $merge) echo "Committed merge $result_commit" -echo $result_commit > .git/HEAD +echo $result_commit > "$GIT_DIR"/HEAD git-checkout-cache -f -a && git-update-cache --refresh git-diff-tree -p ORIG_HEAD HEAD | diffstat -p1 diff --git a/git-tag-script b/git-tag-script index ccc75dcf..281d1928 100755 --- a/git-tag-script +++ b/git-tag-script @@ -1,5 +1,9 @@ #!/bin/sh -object=${2:-$(cat .git/HEAD)} +# Copyright (c) 2005 Linus Torvalds + +: ${GIT_DIR=.git} + +object=${2:-$(cat "$GIT_DIR"/HEAD)} type=$(git-cat-file -t $object) || exit 1 ( echo -e "object $object\ntype $type\ntag $1\n"; cat ) > .tmp-tag rm -f .tmp-tag.asc diff --git a/gitenv.c b/gitenv.c new file mode 100644 index 00000000..ab9396f9 --- /dev/null +++ b/gitenv.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005 Junio C Hamano + */ +#include "cache.h" + +/* + * This array must be sorted by its canonical name, because + * we do look-up by binary search. + */ +static struct backward_compatible_env { + const char *canonical; + const char *old; +} bc_name[] = { + { "GIT_ALTERNATE_OBJECT_DIRECTORIES", "SHA1_FILE_DIRECTORIES" }, + { "GIT_AUTHOR_DATE", "AUTHOR_DATE" }, + { "GIT_AUTHOR_EMAIL", "AUTHOR_EMAIL" }, + { "GIT_AUTHOR_NAME", "AUTHOR_NAME" }, + { "GIT_COMMITTER_EMAIL", "COMMIT_AUTHOR_EMAIL" }, + { "GIT_COMMITTER_NAME", "COMMIT_AUTHOR_NAME" }, + { "GIT_OBJECT_DIRECTORY", "SHA1_FILE_DIRECTORY" }, +}; + +static void warn_old_environment(int pos) +{ + int i; + static int warned = 0; + if (warned) + return; + + warned = 1; + fprintf(stderr, + "warning: Attempting to use %s\n", + bc_name[pos].old); + fprintf(stderr, + "warning: GIT environment variables have been renamed.\n" + "warning: Please adjust your scripts and environment.\n"); + for (i = 0; i < sizeof(bc_name) / sizeof(bc_name[0]); i++) { + /* warning is needed only when old name is there and + * new name is not. + */ + if (!getenv(bc_name[i].canonical) && getenv(bc_name[i].old)) + fprintf(stderr, "warning: old %s => new %s\n", + bc_name[i].old, bc_name[i].canonical); + } +} + +char *gitenv_bc(const char *e) +{ + int first, last; + char *val = getenv(e); + if (val) + die("gitenv_bc called on existing %s; fix the caller.", e); + + first = 0; + last = sizeof(bc_name) / sizeof(bc_name[0]); + while (last > first) { + int next = (last + first) >> 1; + int cmp = strcmp(e, bc_name[next].canonical); + if (!cmp) { + val = getenv(bc_name[next].old); + /* If the user has only old name, warn. + * otherwise stay silent. + */ + if (val) + warn_old_environment(next); + return val; + } + if (cmp < 0) { + last = next; + continue; + } + first = next+1; + } + return NULL; +} diff --git a/init-db.c b/init-db.c index 83f95e8b..b6bb7835 100644 --- a/init-db.c +++ b/init-db.c @@ -5,7 +5,7 @@ */ #include "cache.h" -void safe_create_dir(char *dir) +void safe_create_dir(const char *dir) { if (mkdir(dir, 0755) < 0) { if (errno != EEXIST) { @@ -23,14 +23,16 @@ void safe_create_dir(char *dir) */ int main(int argc, char **argv) { - char *sha1_dir, *path; + const char *sha1_dir; + char *path; int len, i; - safe_create_dir(".git"); - - sha1_dir = getenv(DB_ENVIRONMENT); - if (!sha1_dir) { - sha1_dir = DEFAULT_DB_ENVIRONMENT; + sha1_dir = get_object_directory(); + if (!gitenv(DB_ENVIRONMENT) && !gitenv(GIT_DIR_ENVIRONMENT)) { + /* We create leading paths only when we fall back + * to local .git/objects, at least for now. + */ + safe_create_dir(DEFAULT_GIT_DIR_ENVIRONMENT); fprintf(stderr, "defaulting to local storage area\n"); } len = strlen(sha1_dir); diff --git a/local-pull.c b/local-pull.c index 1eec8927..3a342ab1 100644 --- a/local-pull.c +++ b/local-pull.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "cache.h" #include "commit.h" #include @@ -70,8 +71,7 @@ int fetch(unsigned char *sha1) munmap(map, st.st_size); close(ofd); if (status) - fprintf(stderr, "cannot write %s (%ld bytes)\n", - dest_filename, st.st_size); + fprintf(stderr, "cannot write %s\n", dest_filename); else pull_say("copy %s\n", hex); return status; diff --git a/read-cache.c b/read-cache.c index a6fbf089..da2adf46 100644 --- a/read-cache.c +++ b/read-cache.c @@ -123,10 +123,112 @@ int same_name(struct cache_entry *a, struct cache_entry *b) return ce_namelen(b) == len && !memcmp(a->name, b->name, len); } -int add_cache_entry(struct cache_entry *ce, int ok_to_add) +/* We may be in a situation where we already have path/file and path + * is being added, or we already have path and path/file is being + * added. Either one would result in a nonsense tree that has path + * twice when git-write-tree tries to write it out. Prevent it. + * + * If ok-to-replace is specified, we remove the conflicting entries + * from the cache so the caller should recompute the insert position. + * When this happens, we return non-zero. + */ +static int check_file_directory_conflict(const struct cache_entry *ce, + int ok_to_replace) { - int pos; + int pos, replaced = 0; + const char *path = ce->name; + int namelen = strlen(path); + int stage = ce_stage(ce); + char *pathbuf = xmalloc(namelen + 1); + char *cp; + + memcpy(pathbuf, path, namelen + 1); + + /* + * We are inserting path/file. Do they have path registered at + * the same stage? We need to do this for all the levels of our + * subpath. + */ + cp = pathbuf; + while (1) { + char *ep = strchr(cp, '/'); + if (!ep) + break; + *ep = 0; /* first cut it at slash */ + pos = cache_name_pos(pathbuf, + htons(create_ce_flags(ep-cp, stage))); + if (0 <= pos) { + /* Our leading path component is registered as a file, + * and we are trying to make it a directory. This is + * bad. + */ + if (!ok_to_replace) { + free(pathbuf); + return -1; + } + fprintf(stderr, "removing file '%s' to replace it with a directory to create '%s'.\n", pathbuf, path); + remove_entry_at(pos); + replaced = 1; + } + *ep = '/'; /* then restore it and go downwards */ + cp = ep + 1; + } + free(pathbuf); + + /* Do we have an entry in the cache that makes our path a prefix + * of it? That is, are we creating a file where they already expect + * a directory there? + */ + pos = cache_name_pos(path, + htons(create_ce_flags(namelen, stage))); + + /* (0 <= pos) cannot happen because add_cache_entry() + * should have taken care of that case. + */ + pos = -pos-1; + /* pos would point at an existing entry that would come immediately + * after our path. It could be the same as our path in higher stage, + * or different path but in a lower stage. + * + * E.g. when we are inserting path at stage 2, + * + * 1 path + * pos-> 3 path + * 2 path/file1 + * 3 path/file1 + * 2 path/file2 + * 2 patho + * + * We need to examine pos, ignore it because it is at different + * stage, examine next to find the path/file at stage 2, and + * complain. We need to do this until we are not the leading + * path of an existing entry anymore. + */ + + while (pos < active_nr) { + struct cache_entry *other = active_cache[pos]; + if (strncmp(other->name, path, namelen)) + break; /* it is not our "subdirectory" anymore */ + if ((ce_stage(other) == stage) && + other->name[namelen] == '/') { + if (!ok_to_replace) + return -1; + fprintf(stderr, "removing file '%s' under '%s' to be replaced with a file\n", other->name, path); + remove_entry_at(pos); + replaced = 1; + continue; /* cycle without updating pos */ + } + pos++; + } + return replaced; +} + +int add_cache_entry(struct cache_entry *ce, int option) +{ + int pos; + int ok_to_add = option & ADD_CACHE_OK_TO_ADD; + int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE; pos = cache_name_pos(ce->name, htons(ce->ce_flags)); /* existing match? Just replace it */ @@ -152,6 +254,13 @@ int add_cache_entry(struct cache_entry *ce, int ok_to_add) if (!ok_to_add) return -1; + if (check_file_directory_conflict(ce, ok_to_replace)) { + if (!ok_to_replace) + return -1; + pos = cache_name_pos(ce->name, htons(ce->ce_flags)); + pos = -pos-1; + } + /* Make sure the array is big enough .. */ if (active_nr == active_alloc) { active_alloc = alloc_nr(active_alloc); diff --git a/rsh.c b/rsh.c index 2a52e598..5d1cb9d5 100644 --- a/rsh.c +++ b/rsh.c @@ -36,8 +36,8 @@ int setup_connection(int *fd_in, int *fd_out, char *remote_prog, *(path++) = '\0'; /* ssh 'cd /; stdio-pull ' */ snprintf(command, COMMAND_SIZE, - "cd /%s; SHA1_FILE_DIRECTORY=objects %s", - path, remote_prog); + "cd /%s; %s=objects %s", + path, DB_ENVIRONMENT, remote_prog); posn = command + strlen(command); for (i = 0; i < rmt_argc; i++) { *(posn++) = ' '; diff --git a/sha1_file.c b/sha1_file.c index e21f4b30..942b673d 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -7,6 +7,7 @@ * creation etc. */ #include +#include #include "cache.h" #ifndef O_NOATIME @@ -58,6 +59,38 @@ int get_sha1_file(const char *path, unsigned char *result) return get_sha1_hex(buffer, result); } +static char *git_dir, *git_object_dir, *git_index_file; +static void setup_git_env(void) +{ + git_dir = gitenv(GIT_DIR_ENVIRONMENT); + if (!git_dir) + git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; + git_object_dir = gitenv(DB_ENVIRONMENT); + if (!git_object_dir) { + git_object_dir = xmalloc(strlen(git_dir) + 9); + sprintf(git_object_dir, "%s/objects", git_dir); + } + git_index_file = gitenv(INDEX_ENVIRONMENT); + if (!git_index_file) { + git_index_file = xmalloc(strlen(git_dir) + 7); + sprintf(git_index_file, "%s/index", git_dir); + } +} + +char *get_object_directory(void) +{ + if (!git_object_dir) + setup_git_env(); + return git_object_dir; +} + +char *get_index_file(void) +{ + if (!git_index_file) + setup_git_env(); + return git_index_file; +} + int get_sha1(const char *str, unsigned char *sha1) { static char pathname[PATH_MAX]; @@ -69,15 +102,16 @@ int get_sha1(const char *str, unsigned char *sha1) "refs/snap", NULL }; - const char *gitdir; const char **p; if (!get_sha1_hex(str, sha1)) return 0; - gitdir = ".git"; + if (!git_dir) + setup_git_env(); for (p = prefix; *p; p++) { - snprintf(pathname, sizeof(pathname), "%s/%s/%s", gitdir, *p, str); + snprintf(pathname, sizeof(pathname), "%s/%s/%s", + git_dir, *p, str); if (!get_sha1_file(pathname, sha1)) return 0; } @@ -100,18 +134,34 @@ char * sha1_to_hex(const unsigned char *sha1) return buffer; } +static void fill_sha1_path(char *pathbuf, const unsigned char *sha1) +{ + int i; + for (i = 0; i < 20; i++) { + static char hex[] = "0123456789abcdef"; + unsigned int val = sha1[i]; + char *pos = pathbuf + i*2 + (i > 0); + *pos++ = hex[val >> 4]; + *pos = hex[val & 0xf]; + } +} + /* * NOTE! This returns a statically allocated buffer, so you have to be * careful about using it. Do a "strdup()" if you need to save the * filename. + * + * Also note that this returns the location for creating. Reading + * SHA1 file can happen from any alternate directory listed in the + * DB_ENVIRONMENT environment variable if it is not found in + * the primary object database. */ char *sha1_file_name(const unsigned char *sha1) { - int i; static char *name, *base; if (!base) { - char *sha1_file_directory = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT; + const char *sha1_file_directory = get_object_directory(); int len = strlen(sha1_file_directory); base = xmalloc(len + 60); memcpy(base, sha1_file_directory, len); @@ -120,16 +170,94 @@ char *sha1_file_name(const unsigned char *sha1) base[len+3] = '/'; name = base + len + 1; } - for (i = 0; i < 20; i++) { - static char hex[] = "0123456789abcdef"; - unsigned int val = sha1[i]; - char *pos = name + i*2 + (i > 0); - *pos++ = hex[val >> 4]; - *pos = hex[val & 0xf]; - } + fill_sha1_path(name, sha1); return base; } +static struct alternate_object_database { + char *base; + char *name; +} *alt_odb; + +/* + * Prepare alternate object database registry. + * alt_odb points at an array of struct alternate_object_database. + * This array is terminated with an element that has both its base + * and name set to NULL. alt_odb[n] comes from n'th non-empty + * element from colon separated ALTERNATE_DB_ENVIRONMENT environment + * variable, and its base points at a statically allocated buffer + * that contains "/the/directory/corresponding/to/.git/objects/...", + * while its name points just after the slash at the end of + * ".git/objects/" in the example above, and has enough space to hold + * 40-byte hex SHA1, an extra slash for the first level indirection, + * and the terminating NUL. + * This function allocates the alt_odb array and all the strings + * pointed by base fields of the array elements with one xmalloc(); + * the string pool immediately follows the array. + */ +static void prepare_alt_odb(void) +{ + int pass, totlen, i; + const char *cp, *last; + char *op = 0; + const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : ""; + + /* The first pass counts how large an area to allocate to + * hold the entire alt_odb structure, including array of + * structs and path buffers for them. The second pass fills + * the structure and prepares the path buffers for use by + * fill_sha1_path(). + */ + for (totlen = pass = 0; pass < 2; pass++) { + last = alt; + i = 0; + do { + cp = strchr(last, ':') ? : last + strlen(last); + if (last != cp) { + /* 43 = 40-byte + 2 '/' + terminating NUL */ + int pfxlen = cp - last; + int entlen = pfxlen + 43; + if (pass == 0) + totlen += entlen; + else { + alt_odb[i].base = op; + alt_odb[i].name = op + pfxlen + 1; + memcpy(op, last, pfxlen); + op[pfxlen] = op[pfxlen + 3] = '/'; + op[entlen-1] = 0; + op += entlen; + } + i++; + } + while (*cp && *cp == ':') + cp++; + last = cp; + } while (*cp); + if (pass) + break; + alt_odb = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen); + alt_odb[i].base = alt_odb[i].name = 0; + op = (char*)(&alt_odb[i+1]); + } +} + +static char *find_sha1_file(const unsigned char *sha1, struct stat *st) +{ + int i; + char *name = sha1_file_name(sha1); + + if (!stat(name, st)) + return name; + if (!alt_odb) + prepare_alt_odb(); + for (i = 0; (name = alt_odb[i].name) != NULL; i++) { + fill_sha1_path(name, sha1); + if (!stat(alt_odb[i].base, st)) + return alt_odb[i].base; + } + return NULL; +} + int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, const char *type) { char header[100]; @@ -145,10 +273,15 @@ int check_sha1_signature(unsigned char *sha1, void *map, unsigned long size, con void *map_sha1_file(const unsigned char *sha1, unsigned long *size) { - char *filename = sha1_file_name(sha1); struct stat st; void *map; int fd; + char *filename = find_sha1_file(sha1, &st); + + if (!filename) { + error("cannot map sha1 file %s", sha1_to_hex(sha1)); + return NULL; + } fd = open(filename, O_RDONLY | sha1_file_open_flag); if (fd < 0) { @@ -167,10 +300,6 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size) /* If it failed once, it will probably fail again. Stop using O_NOATIME */ sha1_file_open_flag = 0; } - if (fstat(fd, &st) < 0) { - close(fd); - return NULL; - } map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); if (-1 == (int)(long)map) @@ -315,6 +444,7 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha } snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + fd = mkstemp(tmpfile); if (fd < 0) { fprintf(stderr, "unable to create temporary sha1 filename %s: %s", tmpfile, strerror(errno)); @@ -349,6 +479,7 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha die("unable to write file"); fchmod(fd, 0444); close(fd); + free(compressed); ret = link(tmpfile, filename); if (ret < 0) { @@ -442,12 +573,8 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd) int has_sha1_file(const unsigned char *sha1) { - char *filename = sha1_file_name(sha1); struct stat st; - - if (!stat(filename, &st)) - return 1; - return 0; + return !!find_sha1_file(sha1, &st); } int index_fd(unsigned char *sha1, int fd, struct stat *st) diff --git a/tree.c b/tree.c index d9777bf8..a978c53a 100644 --- a/tree.c +++ b/tree.c @@ -18,7 +18,7 @@ static int read_one_entry(unsigned char *sha1, const char *base, int baselen, co memcpy(ce->name, base, baselen); memcpy(ce->name + baselen, pathname, len+1); memcpy(ce->sha1, sha1, 20); - return add_cache_entry(ce, 1); + return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); } static int read_tree_recursive(void *buffer, unsigned long size, diff --git a/update-cache.c b/update-cache.c index 735d1992..2f5d620f 100644 --- a/update-cache.c +++ b/update-cache.c @@ -13,7 +13,7 @@ * like "update-cache *" and suddenly having all the object * files be revision controlled. */ -static int allow_add = 0, allow_remove = 0, not_new = 0; +static int allow_add = 0, allow_remove = 0, allow_replace = 0, not_new = 0; /* Three functions to allow overloaded pointer return; see linux/err.h */ static inline void *ERR_PTR(long error) @@ -53,14 +53,23 @@ static void fill_stat_cache_info(struct cache_entry *ce, struct stat *st) static int add_file_to_cache(char *path) { - int size, namelen; + int size, namelen, option, status; struct cache_entry *ce; struct stat st; int fd; char *target; - if (lstat(path, &st) < 0) { - if (errno == ENOENT || errno == ENOTDIR) { + status = lstat(path, &st); + if (status < 0 || S_ISDIR(st.st_mode)) { + /* When we used to have "path" and now we want to add + * "path/file", we need a way to remove "path" before + * being able to add "path/file". However, + * "git-update-cache --remove path" would not work. + * --force-remove can be used but this is more user + * friendly, especially since we can do the opposite + * case just fine without --force-remove. + */ + if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) { if (allow_remove) return remove_file_from_cache(path); } @@ -95,7 +104,9 @@ static int add_file_to_cache(char *path) default: return -1; } - return add_cache_entry(ce, allow_add); + option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; + option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; + return add_cache_entry(ce, option); } static int match_data(int fd, void *buffer, unsigned long size) @@ -273,7 +284,7 @@ inside: static int add_cacheinfo(char *arg1, char *arg2, char *arg3) { - int size, len; + int size, len, option; unsigned int mode; unsigned char sha1[20]; struct cache_entry *ce; @@ -294,7 +305,9 @@ static int add_cacheinfo(char *arg1, char *arg2, char *arg3) memcpy(ce->name, arg3, len); ce->ce_flags = htons(len); ce->ce_mode = create_ce_mode(mode); - return add_cache_entry(ce, allow_add); + option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; + option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; + return add_cache_entry(ce, option); } static const char *lockfile_name = NULL; @@ -343,6 +356,10 @@ int main(int argc, char **argv) allow_add = 1; continue; } + if (!strcmp(path, "--replace")) { + allow_replace = 1; + continue; + } if (!strcmp(path, "--remove")) { allow_remove = 1; continue; @@ -352,8 +369,10 @@ int main(int argc, char **argv) continue; } if (!strcmp(path, "--cacheinfo")) { - if (i+3 >= argc || add_cacheinfo(argv[i+1], argv[i+2], argv[i+3])) + if (i+3 >= argc) die("update-cache: --cacheinfo "); + if (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3])) + die("update-cache: --cacheinfo cannot add %s", argv[i+3]); i += 3; continue; } diff --git a/write-tree.c b/write-tree.c index d801d7fb..e3c0a023 100644 --- a/write-tree.c +++ b/write-tree.c @@ -84,7 +84,7 @@ static int write_tree(struct cache_entry **cachep, int maxentries, const char *b int main(int argc, char **argv) { - int i, unmerged; + int i, funny; int entries = read_cache(); unsigned char sha1[20]; @@ -92,18 +92,45 @@ int main(int argc, char **argv) die("write-tree: error reading cache"); /* Verify that the tree is merged */ - unmerged = 0; + funny = 0; for (i = 0; i < entries; i++) { struct cache_entry *ce = active_cache[i]; if (ntohs(ce->ce_flags) & ~CE_NAMEMASK) { - if (++unmerged > 10) { + if (10 < ++funny) { fprintf(stderr, "...\n"); break; } fprintf(stderr, "%s: unmerged (%s)\n", ce->name, sha1_to_hex(ce->sha1)); } } - if (unmerged) + if (funny) + die("write-tree: not able to write tree"); + + /* Also verify that the cache does not have path and path/file + * at the same time. At this point we know the cache has only + * stage 0 entries. + */ + funny = 0; + for (i = 0; i < entries - 1; i++) { + /* path/file always comes after path because of the way + * the cache is sorted. Also path can appear only once, + * which means conflicting one would immediately follow. + */ + const char *this_name = active_cache[i]->name; + const char *next_name = active_cache[i+1]->name; + int this_len = strlen(this_name); + if (this_len < strlen(next_name) && + strncmp(this_name, next_name, this_len) == 0 && + next_name[this_len] == '/') { + if (10 < ++funny) { + fprintf(stderr, "...\n"); + break; + } + fprintf(stderr, "You have both %s and %s\n", + this_name, next_name); + } + } + if (funny) die("write-tree: not able to write tree"); /* Ok, write it out */