diff --git a/Documentation/RelNotes-1.5.3.txt b/Documentation/RelNotes-1.5.3.txt index 9c36e8baeb..f2efaaffb7 100644 --- a/Documentation/RelNotes-1.5.3.txt +++ b/Documentation/RelNotes-1.5.3.txt @@ -28,7 +28,7 @@ Updates since v1.5.2 * For people who need to import from Perforce, a front-end for fast-import is in contrib/fast-import/. -* Comes with git-gui 0.8.0. +* Comes with git-gui 0.8.2. * Comes with updated gitk. @@ -130,6 +130,9 @@ Updates since v1.5.2 - "git init -q" makes the command quieter. + - "git -p command" now has a cousin of opposite sex, "git --no-pager + command". + * Updated behavior of existing commands. - "gitweb" can offer multiple snapshot formats. @@ -172,6 +175,15 @@ Updates since v1.5.2 - "git log" learned --log-size to show the number of bytes in the log message part of the output to help qgit. + - "git log --name-status" does not require you to give "-r" anymore. + As a general rule, Porcelain commands should recurse when showing + diff. + + - "git format-patch --root A" can be used to format everything + since the beginning up to A. This was supported with + "git format-patch --root A A" for a long time, but was not + properly documented. + - "git svn dcommit" retains local merge information. - "git svnimport" allows an empty string to be specified as the @@ -301,8 +313,8 @@ Updates since v1.5.2 when switching branches that have differences in only a handful paths. - - "git commit paths..." has also been optimized. - + - "git add paths..." and "git commit paths..." has also been + heavily optimized. Fixes since v1.5.2 ------------------ @@ -315,8 +327,14 @@ this release, unless otherwise noted. - "gitweb" had trouble handling non UTF-8 text with older Encode.pm Perl module. + - "git-write-tree" had a bad interaction with racy-git avoidance and + gitattributes mechanisms. + + - "git --bare command" overrode existing GIT_DIR setting and always + made it treat the current working directory as GIT_DIR. + -- exec >/var/tmp/1 -O=v1.5.3-rc4 +O=v1.5.3-rc7 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/config.txt b/Documentation/config.txt index de9e72b562..903610fecf 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -192,7 +192,7 @@ core.worktree:: variable and the '--work-tree' command line option. core.logAllRefUpdates:: - Updates to a ref is logged to the file + Enable the reflog. Updates to a ref is logged to the file "$GIT_DIR/logs/", by appending the new and old SHA1, the date/time and the reason of the update, but only when the file exists. If this configuration @@ -283,7 +283,7 @@ core.excludesfile:: core.editor:: Commands such as `commit` and `tag` that lets you edit - messages by lauching an editor uses the value of this + messages by launching an editor uses the value of this variable when it is set, and the environment variable `GIT_EDITOR` is not set. The order of preference is `GIT_EDITOR` environment, `core.editor`, `VISUAL` and @@ -465,11 +465,11 @@ rerere.enabled:: be encountered again. See gitlink:git-rerere[1]. gitcvs.enabled:: - Whether the cvs server interface is enabled for this repository. + Whether the CVS server interface is enabled for this repository. See gitlink:git-cvsserver[1]. gitcvs.logfile:: - Path to a log file where the cvs server interface well... logs + Path to a log file where the CVS server interface well... logs various stuff. See gitlink:git-cvsserver[1]. gitcvs.allbinary:: @@ -500,10 +500,10 @@ gitcvs.dbuser, gitcvs.dbpass:: 'gitcvs.dbuser' supports variable substitution (see gitlink:git-cvsserver[1] for details). -All gitcvs variables except for 'gitcvs.allbinary' can also specifed -as 'gitcvs..' (where 'access_method' is one -of "ext" and "pserver") to make them apply only for the given access -method. +All gitcvs variables except for 'gitcvs.allbinary' can also be +specified as 'gitcvs..' (where 'access_method' +is one of "ext" and "pserver") to make them apply only for the given +access method. http.sslVerify:: Whether to verify the SSL certificate when fetching or pushing @@ -615,7 +615,7 @@ pack.compression:: not set, defaults to -1. pack.deltaCacheSize:: - The maxium memory in bytes used for caching deltas in + The maximum memory in bytes used for caching deltas in gitlink:git-pack-objects[1]. A value of 0 means no limit. Defaults to 0. @@ -675,15 +675,11 @@ showbranch.default:: See gitlink:git-show-branch[1]. tar.umask:: - By default, gitlink:git-tar-tree[1] sets file and directories modes - to 0666 or 0777. While this is both useful and acceptable for projects - such as the Linux Kernel, it might be excessive for other projects. - With this variable, it becomes possible to tell - gitlink:git-tar-tree[1] to apply a specific umask to the modes above. - The special value "user" indicates that the user's current umask will - be used. This should be enough for most projects, as it will lead to - the same permissions as gitlink:git-checkout[1] would use. The default - value remains 0, which means world read-write. + This variable can be used to restrict the permission bits of + tar archive entries. The default is 0002, which turns off the + world write bit. The special value "user" indicates that the + archiving user's umask will be used instead. See umask(2) and + gitlink:git-archive[1]. user.email:: Your email address to be recorded in any newly created commits. diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 3383aca9af..2fe7355555 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -7,7 +7,9 @@ git-add - Add file contents to the index SYNOPSIS -------- -'git-add' [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] ... +[verse] +'git-add' [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] + [--] ... DESCRIPTION ----------- @@ -31,9 +33,9 @@ files have changes that are staged for the next commit. The 'git add' command will not add ignored files by default. If any ignored files were explicitly specified on the command line, 'git add' will fail with a list of ignored files. Ignored files reached by -directory recursion or filename globbing will be silently ignored. -The 'add' command can be used to add ignored files with the `-f` -(force) option. +directory recursion or filename globbing performed by Git (quote your +globs before the shell) will be silently ignored. The 'add' command can +be used to add ignored files with the `-f` (force) option. Please see gitlink:git-commit[1] for alternative ways to add content to a commit. @@ -41,7 +43,7 @@ commit. OPTIONS ------- -...:: +...:: Files to add content from. Fileglobs (e.g. `*.c`) can be given to add all matching files. Also a leading directory name (e.g. `dir` to add `dir/file1` diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt index 4da07c1580..f2080eb6ad 100644 --- a/Documentation/git-archive.txt +++ b/Documentation/git-archive.txt @@ -72,16 +72,13 @@ zip CONFIGURATION ------------- -By default, file and directories modes are set to 0666 or 0777 in tar -archives. It is possible to change this by setting the "umask" variable -in the repository configuration as follows : -[tar] - umask = 002 ;# group friendly - -The special umask value "user" indicates that the user's current umask -will be used instead. The default value remains 0, which means world -readable/writable files and directories. +tar.umask:: + This variable can be used to restrict the permission bits of + tar archive entries. The default is 0002, which turns off the + world write bit. The special value "user" indicates that the + archiving user's umask will be used instead. See umask(2) for + details. EXAMPLES -------- diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 818b720b91..734928bf96 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -35,7 +35,7 @@ working tree. OPTIONS ------- -q:: - Quiet, supress feedback messages. + Quiet, suppress feedback messages. -f:: Proceed even if the index or the working tree differs diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index 5870c2ce47..a2537e179a 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -51,9 +51,9 @@ A commit encapsulates: - 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 by -either `.git/config` file, or using the following environment variables. +While parent object ids are provided on the command line, author and +committer information is taken from the following environment variables, +if set: GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL @@ -65,12 +65,9 @@ either `.git/config` file, or using the following environment variables. (nb "<", ">" and "\n"s are stripped) -In `.git/config` file, the following items are used for GIT_AUTHOR_NAME and -GIT_AUTHOR_EMAIL: - - [user] - name = "Your Name" - email = "your@email.address.xz" +In case (some of) these environment variables are not set, the information +is taken from the configuration items user.name and user.email, or, if not +present, system user name and fully qualified hostname. A commit comment is read from stdin. If a changelog entry is not provided via "<" redirection, "git-commit-tree" will just wait diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index c3dffffe32..5b794f4399 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -139,7 +139,7 @@ See also <>. FILES ----- -If not set explicitely with '--file', there are three files where +If not set explicitly with '--file', there are three files where git-config will search for configuration options: .git/config:: diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index 6c423e3a2f..4c8d1e6386 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -59,7 +59,7 @@ OPTIONS Useful for patch series and the like. -u:: - Update affected files from cvs repository before attempting export. + Update affected files from CVS repository before attempting export. -v:: Verbose. diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index 60d0bcf0f3..258a62f7e9 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -102,7 +102,7 @@ No special setup is needed for SSH access, other than having GIT tools in the PATH. If you have clients that do not accept the CVS_SERVER environment variable, you can rename git-cvsserver to cvs. -Note: Newer cvs versions (>= 1.12.11) also support specifying +Note: Newer CVS versions (>= 1.12.11) also support specifying CVS_SERVER directly in CVSROOT like ------ diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index b36e705dd0..db2eb46a19 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -22,10 +22,10 @@ tree and the index file, or the index file and the working tree. words, the differences are what you _could_ tell git to further add to the index but you still haven't. You can stage these changes by using gitlink:git-add[1]. - - If exactly two paths are given, and at least one is untracked, - compare the two files / directories. This behavior can be - forced by --no-index. ++ +If exactly two paths are given, and at least one is untracked, +compare the two files / directories. This behavior can be +forced by --no-index. 'git-diff' [--options] --cached [] [--] [...]:: @@ -44,16 +44,34 @@ tree and the index file, or the index file and the working tree. 'git-diff' [--options] [--] [...]:: - This form is to view the changes between two , - for example, tips of two branches. + This is to view the changes between two arbitrary + . + +'git-diff' [--options] .. [--] [...]:: + + This is synonymous to the previous form. If on + one side is omitted, it will have the same effect as + using HEAD instead. + +'git-diff' [--options] \... [--] [...]:: + + This form is to view the changes on the branch containing + and up to the second , starting at a common ancestor + of both . "git-diff A\...B" is equivalent to + "git-diff $(git-merge-base A B) B". You can omit any one + of , which has the same effect as using HEAD instead. Just in case if you are doing something exotic, it should be -noted that all of the in the above description can be -any . +noted that all of the in the above description, except +for the last two forms that use ".." notations, can be any +. For a more complete list of ways to spell , see "SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1]. - +However, "diff" is about comparing two _endpoints_, not ranges, +and the range notations (".." and +"\...") do not mean a range as defined in the +"SPECIFYING RANGES" section in gitlink:git-rev-parse[1]. OPTIONS ------- @@ -97,6 +115,18 @@ the tip of the current branch, but limit the comparison to the file "test". <3> Compare the version before the last commit and the last commit. +Comparing branches:: ++ +------------ +$ git diff topic master <1> +$ git diff topic..master <2> +$ git diff topic...master <3> +------------ ++ +<1> Changes between the tips of the topic and the master branches. +<2> Same as above. +<3> Changes that occured on the master branch since when the topic +branch was started off it. Limiting the diff output:: + diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 30ee98d17f..d5119678b5 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -176,6 +176,15 @@ results, such as branch names or file names with leading or trailing spaces in their name, or early termination of fast-import when it encounters unexpected input. +Stream Comments +~~~~~~~~~~~~~~~ +To aid in debugging frontends fast-import ignores any line that +begins with `#` (ASCII pound/hash) up to and including the line +ending `LF`. A comment line may contain any sequence of bytes +that does not contain an LF and therefore may be used to include +any detailed debugging information that might be specific to the +frontend and useful when inspecting a fast-import data stream. + Date Formats ~~~~~~~~~~~~ The following date formats are supported. A frontend should select @@ -232,7 +241,7 @@ been well tested in the wild. + Frontends should prefer the `raw` format if the source material already uses UNIX-epoch format, can be coaxed to give dates in that -format, or its format is easiliy convertible to it, as there is no +format, or its format is easily convertible to it, as there is no ambiguity in parsing. `now`:: @@ -289,6 +298,11 @@ and control the current import process. More detailed discussion This command is optional and is not needed to perform an import. +`progress`:: + Causes fast-import to echo the entire line to its own + standard output. This command is optional and is not needed + to perform an import. + `commit` ~~~~~~~~ Create or update a branch with a new commit, recording one logical @@ -303,7 +317,7 @@ change to the project. ('from' SP LF)? ('merge' SP LF)? (filemodify | filedelete | filecopy | filerename | filedeleteall)* - LF + LF? .... where `` is the name of the branch to make the commit on. @@ -329,11 +343,13 @@ Zero or more `filemodify`, `filedelete`, `filecopy`, `filerename` and `filedeleteall` commands may be included to update the contents of the branch prior to creating the commit. These commands may be supplied in any order. -However it is recommended that a `filedeleteall` command preceed +However it is recommended that a `filedeleteall` command precede all `filemodify`, `filecopy` and `filerename` commands in the same commit, as `filedeleteall` wipes the branch clean (see below). +The `LF` after the command is optional (it used to be required). + `author` ^^^^^^^^ An `author` command may optionally appear, if the author information @@ -386,7 +402,7 @@ Here `` is any of the following: + The reason fast-import uses `:` to denote a mark reference is this character is not legal in a Git branch name. The leading `:` makes it easy -to distingush between the mark 42 (`:42`) and the branch 42 (`42` +to distinguish between the mark 42 (`:42`) and the branch 42 (`42` or `refs/heads/42`), or an abbreviated SHA-1 which happened to consist only of base-10 digits. + @@ -471,7 +487,7 @@ start with double quote (`"`). If an `LF` or double quote must be encoded into `` shell-style quoting should be used, e.g. `"path/with\n and \" in it"`. -The value of `` must be in canoncial form. That is it must not: +The value of `` must be in canonical form. That is it must not: * contain an empty directory component (e.g. `foo//bar` is invalid), * end with a directory separator (e.g. `foo/` is invalid), @@ -645,12 +661,14 @@ branch from an existing commit without creating a new commit. .... 'reset' SP LF ('from' SP LF)? - LF + LF? .... For a detailed description of `` and `` see above under `commit` and `from`. +The `LF` after the command is optional (it used to be required). + The `reset` command can also be used to create lightweight (non-annotated) tags. For example: @@ -689,29 +707,40 @@ intended for production-quality conversions should always use the exact byte count format, as it is more robust and performs better. The delimited format is intended primarily for testing fast-import. +Comment lines appearing within the `` part of `data` commands +are always taken to be part of the body of the data and are therefore +never ignored by fast-import. This makes it safe to import any +file/message content whose lines might start with `#`. + Exact byte count format:: The frontend must specify the number of bytes of data. + .... 'data' SP LF - LF + LF? .... + where `` is the exact number of bytes appearing within ``. The value of `` is expressed as an ASCII decimal integer. The `LF` on either side of `` is not included in `` and will not be included in the imported data. ++ +The `LF` after `` is optional (it used to be required) but +recommended. Always including it makes debugging a fast-import +stream easier as the next command always starts in column 0 +of the next line, even if `` did not end with an `LF`. Delimited format:: A delimiter string is used to mark the end of the data. fast-import will compute the length by searching for the delimiter. - This format is primarly useful for testing and is not + This format is primarily useful for testing and is not recommended for real data. + .... 'data' SP '<<' LF LF LF + LF? .... + where `` is the chosen delimiter string. The string `` @@ -720,6 +749,8 @@ fast-import will think the data ends earlier than it really does. The `LF` immediately trailing `` is part of ``. This is one of the limitations of the delimited format, it is impossible to supply a data chunk which does not have an LF as its last byte. ++ +The `LF` after ` LF` is optional (it used to be required). `checkpoint` ~~~~~~~~~~~~ @@ -728,7 +759,7 @@ save out all current branch refs, tags and marks. .... 'checkpoint' LF - LF + LF? .... Note that fast-import automatically switches packfiles when the current @@ -747,6 +778,32 @@ process access to a branch. However given that a 30 GiB Subversion repository can be loaded into Git through fast-import in about 3 hours, explicit checkpointing may not be necessary. +The `LF` after the command is optional (it used to be required). + +`progress` +~~~~~~~~~~ +Causes fast-import to print the entire `progress` line unmodified to +its standard output channel (file descriptor 1) when the command is +processed from the input stream. The command otherwise has no impact +on the current import, or on any of fast-import's internal state. + +.... + 'progress' SP LF + LF? +.... + +The `` part of the command may contain any sequence of bytes +that does not contain `LF`. The `LF` after the command is optional. +Callers may wish to process the output through a tool such as sed to +remove the leading part of the line, for example: + +==== + frontend | git-fast-import | sed 's/^progress //' +==== + +Placing a `progress` command immediately after a `checkpoint` will +inform the reader when the `checkpoint` has been completed and it +can safely access the refs that fast-import updated. Tips and Tricks --------------- @@ -816,7 +873,7 @@ to remove the dummy branch. Import Now, Repack Later ~~~~~~~~~~~~~~~~~~~~~~~~ As soon as fast-import completes the Git repository is completely valid -and ready for use. Typicallly this takes only a very short time, +and ready for use. Typically this takes only a very short time, even for considerably large projects (100,000+ commits). However repacking the repository is necessary to improve data @@ -840,6 +897,15 @@ This will take longer, but will also produce a smaller packfile. You only need to expend the effort once, and everyone using your project will benefit from the smaller repository. +Include Some Progress Messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Every once in a while have your frontend emit a `progress` message +to fast-import. The contents of the messages are entirely free-form, +so one suggestion would be to output the current month and year +each time the current commit date moves into the next month. +Your users will feel better knowing how much of the data stream +has been processed. + Packfile Optimization --------------------- @@ -876,8 +942,8 @@ Memory Utilization ------------------ There are a number of factors which affect how much memory fast-import requires to perform an import. Like critical sections of core -Git, fast-import uses its own memory allocators to ammortize any overheads -associated with malloc. In practice fast-import tends to ammoritize any +Git, fast-import uses its own memory allocators to amortize any overheads +associated with malloc. In practice fast-import tends to amortize any malloc overheads to 0, due to its use of large block allocations. per object @@ -934,7 +1000,7 @@ per active tree ~~~~~~~~~~~~~~~ Trees (aka directories) use just 12 bytes of memory on top of the memory required for their entries (see ``per active file'' below). -The cost of a tree is virtually 0, as its overhead ammortizes out +The cost of a tree is virtually 0, as its overhead amortizes out over the individual file entries. per active file entry diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 915258f410..8c43be611a 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -120,7 +120,7 @@ have all of them as parents. tag name is expected on standard output. + The original tags are not deleted, but can be overwritten; -use "--tag-name-filter=cat" to simply update the tags. In this +use "--tag-name-filter cat" to simply update the tags. In this case, be very careful and make sure you have the old tags backed up in case the conversion has run afoul. + diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt index 6affc5bb4d..7088ed4095 100644 --- a/Documentation/git-fmt-merge-msg.txt +++ b/Documentation/git-fmt-merge-msg.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] git-fmt-merge-msg [--summary | --no-summary] <$GIT_DIR/FETCH_HEAD -git-fmt-merge-msg [--summary | --no-summray] -F +git-fmt-merge-msg [--summary | --no-summary] -F DESCRIPTION ----------- diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6cbcf937bc..c9857a2d62 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -16,21 +16,35 @@ SYNOPSIS [--in-reply-to=Message-Id] [--suffix=.] [--ignore-if-in-upstream] [--subject-prefix=Subject-Prefix] - [..] + [ | ] DESCRIPTION ----------- -Prepare each commit between and with its patch in +Prepare each commit with its patch in one file per commit, formatted to resemble UNIX mailbox format. -If .. is not specified, the head of the current working -tree is implied. For a more complete list of ways to spell - and , see "SPECIFYING REVISIONS" section in -gitlink:git-rev-parse[1]. - The output of this command is convenient for e-mail submission or for use with gitlink:git-am[1]. +There are two ways to specify which commits to operate on. + +1. A single commit, , specifies that the commits leading + to the tip of the current branch that are not in the history + that leads to the to be output. + +2. Generic expression (see "SPECIFYING + REVISIONS" section in gitlink:git-rev-parse[1]) means the + commits in the specified range. + +A single commit, when interpreted as a +expression, means "everything that leads to that commit", but +if you write 'git format-patch ', the previous rule +applies to that command line and you do not get "everything +since the beginning of the time". If you want to format +everything since project inception to one commit, say "git +format-patch \--root " to make it clear that it is the +latter case. + By default, each output file is numbered sequentially from 1, and uses the first line of the commit message (massaged for pathname safety) as the filename. With the --numbered-files option, the output file names @@ -118,7 +132,7 @@ include::diff-options.txt[] --suffix=.:: Instead of using `.patch` as the suffix for generated - filenames, use specifed suffix. A common alternative is + filenames, use specified suffix. A common alternative is `--suffix=.txt`. + Note that you would need to include the leading dot `.` if you @@ -153,6 +167,10 @@ git-format-patch origin:: not in the origin branch. For each commit a separate file is created in the current directory. +git-format-patch \--root origin:: + Extract all commits which that leads to 'origin' since the + inception of the project. + git-format-patch -M -B origin:: The same as the previous one. Additionally, it detects and handles renames and complete rewrites intelligently to diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt index bd613b2fcf..13252a1aa6 100644 --- a/Documentation/git-gui.txt +++ b/Documentation/git-gui.txt @@ -89,7 +89,7 @@ See Also Other ----- git-gui is actually maintained as an independent project, but stable -versions are distributed as part of the Git suite for the convience +versions are distributed as part of the Git suite for the convenience of end users. A git-gui development repository can be obtained from: diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt index 45e48453a1..389c6edfb8 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.txt @@ -34,7 +34,7 @@ commit-id:: the local end after the transfer is complete. --stdin:: - Instead of a commit id on the commandline (which is not expected in this + Instead of a commit id on the command line (which is not expected in this case), 'git-http-fetch' expects lines on stdin in the format ['\t'] diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index 141b76768c..e830deeff3 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -44,7 +44,7 @@ OPTIONS the local end after the transfer is complete. --stdin:: - Instead of a commit id on the commandline (which is not expected in this + Instead of a commit id on the command line (which is not expected in this case), 'git-local-fetch' expects lines on stdin in the format ['\t'] diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 5a90f65b5e..5ec547cc0c 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -49,6 +49,7 @@ include::pretty-options.txt[] -g, \--walk-reflogs:: Show commits as they were recorded in the reflog. The log contains a record about how the tip of a reference was changed. + Cannot be combined with --reverse. See also gitlink:git-reflog[1]. --decorate:: @@ -95,7 +96,7 @@ git log --since="2 weeks ago" \-- gitk:: The "--" is necessary to avoid confusion with the *branch* named 'gitk' -git log -r --name-status release..test:: +git log --name-status release..test:: Show the commits that are in the "test" branch but not yet in the "release" branch, along with the list of paths diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt index 91eede120e..306e1a4956 100644 --- a/Documentation/git-name-rev.txt +++ b/Documentation/git-name-rev.txt @@ -37,7 +37,7 @@ OPTIONS --name-only:: Instead of printing both the SHA-1 and the name, print only the name. If given with --tags the usual tag prefix of - "tags/" is also ommitted from the name, matching the output + "tags/" is also omitted from the name, matching the output of gitlink::git-describe[1] more closely. This option cannot be combined with --stdin. diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index 4ef1840472..2633d94c59 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -78,7 +78,7 @@ The hook should exit with non-zero status if it wants to disallow updating the named ref. Otherwise it should exit with zero. Successful execution (a zero exit status) of this hook does not -ensure the ref will actully be updated, it is only a prerequisite. +ensure the ref will actually be updated, it is only a prerequisite. As such it is not a good idea to send notices (e.g. email) from this hook. Consider using the post-receive hook instead. diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 89bc9c51ea..5180f6810d 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -30,9 +30,10 @@ Entries older than `expire` time, or entries older than tip, are removed from the reflog. This is typically not used directly by the end users -- instead, see gitlink:git-gc[1]. -The subcommand "show" (which is also the default, in the absense of any +The subcommand "show" (which is also the default, in the absence of any subcommands) will take all the normal log options, and show the log of -the current branch. It is basically an alias for 'git log -g --abbrev-commit +`HEAD`, which will cover all recent actions, including branch switches. +It is basically an alias for 'git log -g --abbrev-commit --pretty=oneline', see gitlink:git-log[1]. diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 5283ef84a9..12e2079a7c 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -14,7 +14,7 @@ DESCRIPTION ----------- This script is used to combine all objects that do not currently -reside in a "pack", into a pack. It can also be used to re-organise +reside in a "pack", into a pack. It can also be used to re-organize existing packs into a single, more efficient pack. A pack is a collection of objects, individually compressed, with diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 1c1978140f..7cd0e8913e 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -113,7 +113,7 @@ e.g. "2 hours ago". `--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822 format, often found in E-mail messages. + -`--date=short` shows only date but not time, in `YYYY-MM-DD` fomat. +`--date=short` shows only date but not time, in `YYYY-MM-DD` format. + `--date=default` shows timestamps in the original timezone (either committer's or author's). @@ -299,6 +299,8 @@ used in the output. When the starting commit is specified as instead. Under '\--pretty=oneline', the commit message is prefixed with this information on the same line. +Cannot be combined with '\--reverse'. + --merge:: After a failed merge, show refs that touch files having a @@ -373,6 +375,7 @@ By default, the commits are shown in reverse chronological order. --reverse:: Output the commits in reverse order. + Cannot be combined with '\--walk-reflogs'. Object Traversal ~~~~~~~~~~~~~~~~ diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 4b4d229e60..4758c33dee 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -215,7 +215,10 @@ blobs contained in a commit. * A colon, optionally followed by a stage number (0 to 3) and a colon, followed by a path; this names a blob object in the index at the given path. Missing stage number (and the colon - that follows it) names an stage 0 entry. + that follows it) names an stage 0 entry. During a merge, stage + 1 is the common ancestor, stage 2 is the target branch's version + (typically the current branch), and stage 3 is the version from + the branch being merged. Here is an illustration, by Jon Loeliger. Both node B and C are a commit parents of commit node A. Parent commits are ordered diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index d243ed1e3a..8231286e09 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -62,7 +62,7 @@ The --cc option must be repeated for each user you want on the cc list. --signed-off-by-cc, --no-signed-off-by-cc:: If this is set, add emails found in Signed-off-by: or Cc: lines to the cc list. - Default is the value of 'sendemail.signedoffbycc' configuration value; + Default is the value of 'sendemail.signedoffcc' configuration value; if that is unspecified, default to --signed-off-by-cc. --quiet:: @@ -88,7 +88,7 @@ The --cc option must be repeated for each user you want on the cc list. If this is set, do not add the From: address to the cc: list, if it shows up in a From: line. Default is the value of 'sendemail.suppressfrom' configuration value; - if that is unspecified, default to --no-supress-from. + if that is unspecified, default to --no-suppress-from. --thread, --no-thread:: If this is set, the In-Reply-To header will be set on each email sent. diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 816340b944..be2e34eb8f 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -44,10 +44,15 @@ COMMANDS --tags=;; -b;; --branches=;; +-s;; +--stdlayout;; These are optional command-line options for init. Each of these flags can point to a relative repository path (--tags=project/tags') or a full url - (--tags=https://foo.org/project/tags) + (--tags=https://foo.org/project/tags). The option --stdlayout is + a shorthand way of setting trunk,tags,branches as the relative paths, + which is the Subversion default. If any of the other options are given + as well, they take precedence. --no-metadata;; Set the 'noMetadata' option in the [svn-remote] config. --use-svm-props;; @@ -94,7 +99,7 @@ COMMANDS This works similarly to 'svn update' or 'git-pull' except that it preserves linear history with 'git-rebase' instead of -'git-merge' for ease of dcommit-ing with git-svn. +'git-merge' for ease of dcommiting with git-svn. This accepts all options that 'git-svn fetch' and 'git-rebase' accepts. However '--fetch-all' only fetches from the current @@ -479,6 +484,38 @@ the user on the git side. git-svn does however follow copy history of the directory that it is tracking, however (much like how 'svn log' works). +CAVEATS +------- + +For the sake of simplicity and interoperating with a less-capable system +(SVN), it is recommended that all git-svn users clone, fetch and dcommit +directly from the SVN server, and avoid all git-clone/pull/merge/push +operations between git repositories and branches. The recommended +method of exchanging code between git branches and users is +git-format-patch and git-am, or just dcommiting to the SVN repository. + +Running 'git-merge' or 'git-pull' is NOT recommended on a branch you +plan to dcommit from. Subversion does not represent merges in any +reasonable or useful fashion; so users using Subversion cannot see any +merges you've made. Furthermore, if you merge or pull from a git branch +that is a mirror of an SVN branch, dcommit may commit to the wrong +branch. + +'git-clone' does not clone branches under the refs/remotes/ hierarchy or +any git-svn metadata, or config. So repositories created and managed with +using git-svn should use rsync(1) for cloning, if cloning is to be done +at all. + +Since 'dcommit' uses rebase internally, any git branches you git-push to +before dcommit on will require forcing an overwrite of the existing ref +on the remote repository. This is generally considered bad practice, +see the git-push(1) documentation for details. + +Do not use the --amend option of git-commit(1) on a change you've +already dcommitted. It is considered bad practice to --amend commits +you've already pushed to a remote repository for other users, and +dcommit with SVN is analogous to that. + BUGS ---- @@ -512,9 +549,9 @@ listed below are allowed: ------------------------------------------------------------------------ Keep in mind that the '*' (asterisk) wildcard of the local ref -(left of the ':') *must* be the farthest right path component; +(right of the ':') *must* be the farthest right path component; however the remote wildcard may be anywhere as long as it's own -independent path componet (surrounded by '/' or EOL). This +independent path component (surrounded by '/' or EOL). This type of configuration is not automatically created by 'init' and should be manually entered with a text-editor or using gitlink:git-config[1] diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index e97d15e8f2..71aad8b45b 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -68,6 +68,9 @@ When importing incrementally, you might need to edit the .git/svn2git file. Prepend 'rX: ' to commit messages, where X is the imported subversion revision. +-u:: + Replace underscores in tag names with periods. + -I :: Import the svn:ignore directory property to files with this name in each directory. (The Subversion and GIT ignore diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 119117f0bd..990ae4f948 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -34,13 +34,6 @@ A GnuPG signed tag object will be created when `-s` or `-u committer identity for the current user is used to find the GnuPG key for signing. -`-d ` deletes the tag. - -`-v ` verifies the gpg signature of the tag. - -`-l ` lists tags with names that match the given pattern -(or all if no pattern is given). - OPTIONS ------- -a:: diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 2d01d9666f..434607bfb5 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -42,16 +42,13 @@ OPTIONS CONFIGURATION ------------- -By default, file and directories modes are set to 0666 or 0777. It is -possible to change this by setting the "umask" variable in the -repository configuration as follows : -[tar] - umask = 002 ;# group friendly - -The special umask value "user" indicates that the user's current umask -will be used instead. The default value is 002, which means group -readable/writable files and directories. +tar.umask:: + This variable can be used to restrict the permission bits of + tar archive entries. The default is 0002, which turns off the + world write bit. The special value "user" indicates that the + archiving user's umask will be used instead. See umask(2) for + details. EXAMPLES -------- diff --git a/Documentation/git.txt b/Documentation/git.txt index 8017997fb9..75b3e1b87c 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -9,7 +9,8 @@ git - the stupid content tracker SYNOPSIS -------- [verse] -'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate] +'git' [--version] [--exec-path[=GIT_EXEC_PATH]] + [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS] @@ -103,6 +104,9 @@ OPTIONS -p|--paginate:: Pipe all output into 'less' (or if set, $PAGER). +--no-pager:: + Do not pipe git output into a pager. + --git-dir=:: Set the path to the repository. This can also be controlled by setting the GIT_DIR environment variable. @@ -116,7 +120,10 @@ OPTIONS variable. --bare:: - Same as --git-dir=`pwd`. + Treat the repository as a bare repository. If GIT_DIR + environment is not set, it is set to the current working + directory. + FURTHER DOCUMENTATION --------------------- diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 8b90a5b980..46f9d591aa 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -285,7 +285,7 @@ want to appear as the hunk header, like this: Note. A single level of backslashes are eaten by the configuration file parser, so you would need to double the backslashes; the pattern above picks a line that begins with a -backslash, and zero or more occurences of `sub` followed by +backslash, and zero or more occurrences of `sub` followed by `section` followed by open brace, to the end of line. There are a few built-in patterns to make this easier, and `tex` @@ -394,7 +394,7 @@ abc -foo -bar the attributes given to path `t/abc` are computed as follows: 1. By examining `t/.gitattributes` (which is in the same - diretory as the path in question), git finds that the first + directory as the path in question), git finds that the first line matches. `merge` attribute is set. It also finds that the second line matches, and attributes `foo` and `bar` are unset. @@ -410,7 +410,7 @@ the attributes given to path `t/abc` are computed as follows: a match, and `foo` is set, `bar` is reverted to unspecified state, and `baz` is unset. -As the result, the attributes assignement to `t/abc` becomes: +As the result, the attributes assignment to `t/abc` becomes: ---------------------------------------------------------------- foo set to true diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index 6836477ca8..c39edc57c4 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -176,7 +176,7 @@ hook does on its standard input. This hook does not affect the outcome of `git-receive-pack`, as it is called after the real work is done. -This supersedes the <> hook in that it get's +This supersedes the <> hook in that it gets both old and new values of all the refs in addition to their names. diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index bd9fbee99a..fff1068c54 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -339,7 +339,7 @@ $ git pull . remotes/bob/master ------------------------------------- Note that git pull always merges into the current branch, -regardless of what else is given on the commandline. +regardless of what else is given on the command line. Later, Bob can update his repo with Alice's latest changes using diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index f89952ad84..35298e626b 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -4,7 +4,7 @@ ______________________________________________ Git is a fast distributed revision control system. -This manual is designed to be readable by someone with basic unix +This manual is designed to be readable by someone with basic UNIX command-line skills, but no previous knowledge of git. <> and <> explain how @@ -42,10 +42,9 @@ How to get a git repository It will be useful to have a git repository to experiment with as you read this manual. -The best way to get one is by using the gitlink:git-clone[1] command -to download a copy of an existing repository for a project that you -are interested in. If you don't already have a project in mind, here -are some interesting examples: +The best way to get one is by using the gitlink:git-clone[1] command to +download a copy of an existing repository. If you don't already have a +project in mind, here are some interesting examples: ------------------------------------------------ # git itself (approx. 10MB download): @@ -63,21 +62,18 @@ directory, you will see that it contains a copy of the project files, together with a special top-level directory named ".git", which contains all the information about the history of the project. -In most of the following, examples will be taken from one of the two -repositories above. - [[how-to-check-out]] How to check out a different version of a project ------------------------------------------------- -Git is best thought of as a tool for storing the history of a -collection of files. It stores the history as a compressed -collection of interrelated snapshots (versions) of the project's -contents. +Git is best thought of as a tool for storing the history of a collection +of files. It stores the history as a compressed collection of +interrelated snapshots of the project's contents. In git each such +version is called a <>. A single git repository may contain multiple branches. It keeps track of them by keeping a list of <> which reference the -latest version on each branch; the gitlink:git-branch[1] command shows +latest commit on each branch; the gitlink:git-branch[1] command shows you the list of branch heads: ------------------------------------------------ @@ -149,32 +145,27 @@ current branch: ------------------------------------------------ $ git show -commit 2b5f6dcce5bf94b9b119e9ed8d537098ec61c3d2 -Author: Jamal Hadi Salim -Date: Sat Dec 2 22:22:25 2006 -0800 +commit 17cf781661e6d38f737f15f53ab552f1e95960d7 +Author: Linus Torvalds +Date: Tue Apr 19 14:11:06 2005 -0700 - [XFRM]: Fix aevent structuring to be more complete. + Remove duplicate getenv(DB_ENVIRONMENT) call - aevents can not uniquely identify an SA. We break the ABI with this - patch, but consensus is that since it is not yet utilized by any - (known) application then it is fine (better do it now than later). + Noted by Tony Luck. - Signed-off-by: Jamal Hadi Salim - Signed-off-by: David S. Miller - -diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt -index 8be626f..d7aac9d 100644 ---- a/Documentation/networking/xfrm_sync.txt -+++ b/Documentation/networking/xfrm_sync.txt -@@ -47,10 +47,13 @@ aevent_id structure looks like: - - struct xfrm_aevent_id { - struct xfrm_usersa_id sa_id; -+ xfrm_address_t saddr; - __u32 flags; -+ __u32 reqid; - }; -... +diff --git a/init-db.c b/init-db.c +index 65898fa..b002dc6 100644 +--- a/init-db.c ++++ b/init-db.c +@@ -7,7 +7,7 @@ + + int main(int argc, char **argv) + { +- char *sha1_dir = getenv(DB_ENVIRONMENT), *path; ++ char *sha1_dir, *path; + int len, i; + + if (mkdir(".git", 0755) < 0) { ------------------------------------------------ As you can see, a commit shows who made the latest change, what they @@ -217,7 +208,7 @@ commits will help understand how the git organizes history. In the following, we say that commit X is "reachable" from commit Y if commit X is an ancestor of commit Y. Equivalently, you could say -that Y is a descendent of X, or that there is a chain of parents +that Y is a descendant of X, or that there is a chain of parents leading from commit Y to commit X. [[history-diagrams]] @@ -923,14 +914,14 @@ they look OK. [[Finding-comments-with-given-content]] Finding commits referencing a file with given content ------------------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Somebody hands you a copy of a file, and asks which commits modified a file such that it contained the given content either before or after the commit. You can find out with this: ------------------------------------------------- -$ git log --raw -r --abbrev=40 --pretty=oneline -- filename | +$ git log --raw --abbrev=40 --pretty=oneline -- filename | grep -B 1 `git hash-object filename` ------------------------------------------------- @@ -1105,20 +1096,14 @@ backup files made by your editor. Of course, 'not' tracking files with git is just a matter of 'not' calling "`git add`" on them. But it quickly becomes annoying to have these untracked files lying around; e.g. they make "`git add .`" and "`git commit -a`" practically useless, and they keep -showing up in the output of "`git status`", etc. +showing up in the output of "`git status`". -Git therefore provides "exclude patterns" for telling git which files to -actively ignore. Exclude patterns are thoroughly explained in the -gitlink:gitignore[5] manual page, but the heart of the concept is simply -a list of files which git should ignore. Entries in the list may contain -globs to specify multiple files, or may be prefixed by "`!`" to -explicitly include (un-ignore) a previously excluded (ignored) file -(i.e. later exclude patterns override earlier ones). The following -example should illustrate such patterns: +You can tell git to ignore certain files by creating a file called .gitignore +in the top level of your working directory, with contents such as: ------------------------------------------------- # Lines starting with '#' are considered comments. -# Ignore foo.txt. +# Ignore any file named foo.txt. foo.txt # Ignore (generated) html files, *.html @@ -1128,41 +1113,20 @@ foo.txt *.[oa] ------------------------------------------------- -The next question is where to put these exclude patterns so that git can -find them. Git looks for exclude patterns in the following files: +See gitlink:gitignore[5] for a detailed explanation of the syntax. You can +also place .gitignore files in other directories in your working tree, and they +will apply to those directories and their subdirectories. The `.gitignore` +files can be added to your repository like any other files (just run `git add +.gitignore` and `git commit`, as usual), which is convenient when the exclude +patterns (such as patterns matching build output files) would also make sense +for other users who clone your repository. -`.gitignore` files in your working tree::: - You may store multiple `.gitignore` files at various locations in your - working tree. Each `.gitignore` file is applied to the directory where - it's located, including its subdirectories. Furthermore, the - `.gitignore` files can be tracked like any other files in your working - tree; just do a "`git add .gitignore`" and commit. `.gitignore` is - therefore the right place to put exclude patterns that are meant to - be shared between all project participants, such as build output files - (e.g. `\*.o`), etc. -`.git/info/exclude` in your repo::: - Exclude patterns in this file are applied to the working tree as a - whole. Since the file is not located in your working tree, it does - not follow push/pull/clone like `.gitignore` can do. This is therefore - the place to put exclude patterns that are local to your copy of the - repo (i.e. 'not' shared between project participants), such as - temporary backup files made by your editor (e.g. `\*~`), etc. -The file specified by the `core.excludesfile` config directive::: - By setting the `core.excludesfile` config directive you can tell git - where to find more exclude patterns (see gitlink:git-config[1] for - more information on configuration options). This config directive - can be set in the per-repo `.git/config` file, in which case the - exclude patterns will apply to that repo only. Alternatively, you - can set the directive in the global `~/.gitconfig` file to apply - the exclude pattern to all your git repos. As with the above - `.git/info/exclude` (and, indeed, with git config directives in - general), this directive does not follow push/pull/clone, but remain - local to your repo(s). - -[NOTE] -In addition to the above alternatives, there are git commands that can take -exclude patterns directly on the command line. See gitlink:git-ls-files[1] -for an example of this. +If you wish the exclude patterns to affect only certain repositories +(instead of every repository for a given project), you may instead put +them in a file in your repository named .git/info/exclude, or in any file +specified by the `core.excludesfile` configuration variable. Some git +commands can also take exclude patterns directly on the command line. +See gitlink:gitignore[5] for the details. [[how-to-merge]] How to merge @@ -1796,11 +1760,12 @@ taken from the message containing each patch. Public git repositories ----------------------- -Another way to submit changes to a project is to tell the maintainer of -that project to pull the changes from your repository using git-pull[1]. -In the section "<>" we described this as a way to get updates from the "main" -repository, but it works just as well in the other direction. +Another way to submit changes to a project is to tell the maintainer +of that project to pull the changes from your repository using +gitlink:git-pull[1]. In the section "<>" we described this as a way to get +updates from the "main" repository, but it works just as well in the +other direction. If you and the maintainer both have accounts on the same machine, then you can just pull changes from each other's repositories directly; @@ -1911,7 +1876,7 @@ gitlink:git-update-server-info[1], and the documentation link:hooks.html[Hooks used by git].) Advertise the url of proj.git. Anybody else should then be able to -clone or pull from that url, for example with a commandline like: +clone or pull from that url, for example with a command line like: ------------------------------------------------- $ git clone http://yourserver.com/~you/proj.git @@ -2057,7 +2022,8 @@ $ cd work Linus's tree will be stored in the remote branch named origin/master, and can be updated using gitlink:git-fetch[1]; you can track other public trees using gitlink:git-remote[1] to set up a "remote" and -git-fetch[1] to keep them up-to-date; see <>. +gitlink:git-fetch[1] to keep them up-to-date; see +<>. Now create the branches in which you are going to work; these start out at the current tip of origin/master branch, and should be set up (using @@ -2512,9 +2478,9 @@ $ gitk origin..mywork & And browse through the list of patches in the mywork branch using gitk, applying them (possibly in a different order) to mywork-new using cherry-pick, and possibly modifying them as you go using commit --amend. -The git-gui[1] command may also help as it allows you to individually -select diff hunks for inclusion in the index (by right-clicking on the -diff hunk and choosing "Stage Hunk for Commit"). +The gitlink:git-gui[1] command may also help as it allows you to +individually select diff hunks for inclusion in the index (by +right-clicking on the diff hunk and choosing "Stage Hunk for Commit"). Another technique is to use git-format-patch to create a series of patches, then reset the state to before the patches: @@ -2531,7 +2497,7 @@ them again with gitlink:git-am[1]. Other tools ----------- -There are numerous other tools, such as stgit, which exist for the +There are numerous other tools, such as StGIT, which exist for the purpose of maintaining a patch series. These are outside of the scope of this manual. @@ -3961,8 +3927,8 @@ This is a work in progress. The basic requirements: - It must be readable in order, from beginning to end, by - someone intelligent with a basic grasp of the unix - commandline, but without any special knowledge of git. If + someone intelligent with a basic grasp of the UNIX + command line, but without any special knowledge of git. If necessary, any other prerequisites should be specifically mentioned as they arise. - Whenever possible, section headings should clearly describe diff --git a/builtin-add.c b/builtin-add.c index 3dd4ded937..105a9f0e1f 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -14,7 +14,7 @@ #include "revision.h" static const char builtin_add_usage[] = -"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] ..."; +"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] ..."; static int take_worktree_changes; static const char *excludes_file; @@ -155,7 +155,7 @@ static int git_add_config(const char *var, const char *value) static struct lock_file lock_file; -static const char ignore_warning[] = +static const char ignore_error[] = "The following paths are ignored by one of your .gitignore files:\n"; int cmd_add(int argc, const char **argv, const char *prefix) @@ -250,12 +250,12 @@ int cmd_add(int argc, const char **argv, const char *prefix) die("index file corrupt"); if (dir.ignored_nr) { - fprintf(stderr, ignore_warning); + fprintf(stderr, ignore_error); for (i = 0; i < dir.ignored_nr; i++) { fprintf(stderr, "%s\n", dir.ignored[i]->name); } fprintf(stderr, "Use -f if you really want to add them.\n"); - exit(1); + die("no files added"); } for (i = 0; i < dir.nr; i++) diff --git a/builtin-blame.c b/builtin-blame.c index 0519339098..dc88a953a5 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -98,6 +98,10 @@ static char *fill_origin_blob(struct origin *o, mmfile_t *file) num_read_blob++; file->ptr = read_sha1_file(o->blob_sha1, &type, (unsigned long *)(&(file->size))); + if (!file->ptr) + die("Cannot read blob %s for path %s", + sha1_to_hex(o->blob_sha1), + o->path); o->file = *file; } else @@ -1384,6 +1388,9 @@ static void get_commit_info(struct commit *commit, unsigned long size; commit->buffer = read_sha1_file(commit->object.sha1, &type, &size); + if (!commit->buffer) + die("Cannot read commit %s", + sha1_to_hex(commit->object.sha1)); } ret->author = author_buf; get_ac_line(commit->buffer, "\nauthor ", @@ -2382,6 +2389,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix) sb.final_buf = read_sha1_file(o->blob_sha1, &type, &sb.final_buf_size); + if (!sb.final_buf) + die("Cannot read blob %s for path %s", + sha1_to_hex(o->blob_sha1), + path); } num_read_blob++; lno = prepare_lines(&sb); diff --git a/builtin-init-db.c b/builtin-init-db.c index c51c586141..cc0346d575 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -277,6 +277,44 @@ static int create_default_files(const char *git_dir, const char *template_path) return reinit; } +static void guess_repository_type(const char *git_dir) +{ + char cwd[PATH_MAX]; + const char *slash; + + if (0 <= is_bare_repository_cfg) + return; + if (!git_dir) + return; + + /* + * "GIT_DIR=. git init" is always bare. + * "GIT_DIR=`pwd` git init" too. + */ + if (!strcmp(".", git_dir)) + goto force_bare; + if (!getcwd(cwd, sizeof(cwd))) + die("cannot tell cwd"); + if (!strcmp(git_dir, cwd)) + goto force_bare; + /* + * "GIT_DIR=.git or GIT_DIR=something/.git is usually not. + */ + if (!strcmp(git_dir, ".git")) + return; + slash = strrchr(git_dir, '/'); + if (slash && !strcmp(slash, "/.git")) + return; + + /* + * Otherwise it is often bare. At this point + * we are just guessing. + */ + force_bare: + is_bare_repository_cfg = 1; + return; +} + static const char init_db_usage[] = "git-init [-q | --quiet] [--template=] [--shared]"; @@ -309,11 +347,28 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) usage(init_db_usage); } - git_work_tree_cfg = xcalloc(PATH_MAX, 1); - if (!getcwd(git_work_tree_cfg, PATH_MAX)) - die ("Cannot access current working directory."); - if (access(get_git_work_tree(), X_OK)) - die ("Cannot access work tree '%s'", get_git_work_tree()); + /* + * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR + * without --bare. Catch the error early. + */ + git_dir = getenv(GIT_DIR_ENVIRONMENT); + if ((!git_dir || is_bare_repository_cfg == 1) + && getenv(GIT_WORK_TREE_ENVIRONMENT)) + die("%s (or --work-tree=) not allowed without " + "specifying %s (or --git-dir=)", + GIT_WORK_TREE_ENVIRONMENT, + GIT_DIR_ENVIRONMENT); + + guess_repository_type(git_dir); + + if (is_bare_repository_cfg <= 0) { + git_work_tree_cfg = xcalloc(PATH_MAX, 1); + if (!getcwd(git_work_tree_cfg, PATH_MAX)) + die ("Cannot access current working directory."); + if (access(get_git_work_tree(), X_OK)) + die ("Cannot access work tree '%s'", + get_git_work_tree()); + } /* * Set up the default .git directory contents diff --git a/builtin-log.c b/builtin-log.c index 13bae3110e..fa81c25920 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -55,6 +55,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; + rev->diffopt.recursive = 1; rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); @@ -116,7 +117,6 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.simplify_history = 0; cmd_log_init(argc, argv, prefix, &rev); if (!rev.diffopt.output_format) @@ -165,7 +165,6 @@ int cmd_show(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.combine_merges = 1; rev.dense_combined_merges = 1; rev.always_show_header = 1; @@ -586,12 +585,19 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (rev.pending.nr == 1) { - if (rev.max_count < 0) { + if (rev.max_count < 0 && !rev.show_root_diff) { + /* + * This is traditional behaviour of "git format-patch + * origin" that prepares what the origin side still + * does not have. + */ rev.pending.objects[0].item->flags |= UNINTERESTING; add_head(&rev); } - /* Otherwise, it is "format-patch -22 HEAD", and - * get_revision() would return only the specified count. + /* + * Otherwise, it is "format-patch -22 HEAD", and/or + * "format-patch --root HEAD". The user wants + * get_revision() to do the usual traversal. */ } diff --git a/builtin-name-rev.c b/builtin-name-rev.c index 61eba343ab..03083e9477 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -11,14 +11,17 @@ static const char name_rev_usage[] = typedef struct rev_name { const char *tip_name; - int merge_traversals; int generation; + int distance; } rev_name; static long cutoff = LONG_MAX; +/* How many generations are maximally preferred over _one_ merge traversal? */ +#define MERGE_TRAVERSAL_WEIGHT 65535 + static void name_rev(struct commit *commit, - const char *tip_name, int merge_traversals, int generation, + const char *tip_name, int generation, int distance, int deref) { struct rev_name *name = (struct rev_name *)commit->util; @@ -45,13 +48,11 @@ static void name_rev(struct commit *commit, name = xmalloc(sizeof(rev_name)); commit->util = name; goto copy_data; - } else if (name->merge_traversals > merge_traversals || - (name->merge_traversals == merge_traversals && - name->generation > generation)) { + } else if (name->distance > distance) { copy_data: name->tip_name = tip_name; - name->merge_traversals = merge_traversals; name->generation = generation; + name->distance = distance; } else return; @@ -74,11 +75,11 @@ copy_data: sprintf(new_name, "%.*s^%d", len, tip_name, parent_number); - name_rev(parents->item, new_name, - merge_traversals + 1 , 0, 0); + name_rev(parents->item, new_name, 0, + distance + MERGE_TRAVERSAL_WEIGHT, 0); } else { - name_rev(parents->item, tip_name, merge_traversals, - generation + 1, 0); + name_rev(parents->item, tip_name, generation + 1, + distance + 1, 0); } } } diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 24926db27a..9b3ef94c4c 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -979,6 +979,8 @@ static void add_pbase_object(struct tree_desc *tree, int cmp; while (tree_entry(tree,&entry)) { + if (S_ISGITLINK(entry.mode)) + continue; cmp = tree_entry_len(entry.path, entry.sha1) != cmplen ? 1 : memcmp(name, entry.path, cmplen); if (cmp > 0) @@ -1354,6 +1356,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { trg->data = read_sha1_file(trg_entry->idx.sha1, &type, &sz); + if (!trg->data) + die("object %s cannot be read", + sha1_to_hex(trg_entry->idx.sha1)); if (sz != trg_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(trg_entry->idx.sha1), sz, trg_size); @@ -1361,6 +1366,9 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, } if (!src->data) { src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz); + if (!src->data) + die("object %s cannot be read", + sha1_to_hex(src_entry->idx.sha1)); if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(src_entry->idx.sha1), sz, src_size); diff --git a/builtin-write-tree.c b/builtin-write-tree.c index 88f34ba7d6..b89d02efec 100644 --- a/builtin-write-tree.c +++ b/builtin-write-tree.c @@ -72,6 +72,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) const char *prefix = NULL; unsigned char sha1[20]; + git_config(git_default_config); while (1 < argc) { const char *arg = argv[1]; if (!strcmp(arg, "--missing-ok")) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 82b9ed40d8..a652c88b27 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -419,7 +419,7 @@ _git_add () local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in --*) - __gitcomp "--interactive" + __gitcomp "--interactive --refresh" return esac COMPREPLY=() @@ -459,6 +459,35 @@ _git_branch () __gitcomp "$(__git_refs)" } +_git_bundle () +{ + local mycword="$COMP_CWORD" + case "${COMP_WORDS[0]}" in + git) + local cmd="${COMP_WORDS[2]}" + mycword="$((mycword-1))" + ;; + git-bundle*) + local cmd="${COMP_WORDS[1]}" + ;; + esac + case "$mycword" in + 1) + __gitcomp "create list-heads verify unbundle" + ;; + 2) + # looking for a file + ;; + *) + case "$cmd" in + create) + __git_complete_revlist + ;; + esac + ;; + esac +} + _git_checkout () { __gitcomp "$(__git_refs)" @@ -496,6 +525,11 @@ _git_commit () COMPREPLY=() } +_git_describe () +{ + __gitcomp "$(__git_refs)" +} + _git_diff () { __git_complete_file @@ -544,6 +578,7 @@ _git_format_patch () --stdout --attach --thread --output-directory --numbered --start-number + --numbered-files --keep-subject --signoff --in-reply-to= @@ -561,7 +596,7 @@ _git_gc () local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in --*) - __gitcomp "--prune" + __gitcomp "--prune --aggressive" return ;; esac @@ -588,14 +623,20 @@ _git_log () " "" "${cur##--pretty=}" return ;; + --date=*) + __gitcomp " + relative iso8601 rfc2822 short local default + " "" "${cur##--date=}" + return + ;; --*) __gitcomp " --max-count= --max-age= --since= --after= --min-age= --before= --until= --root --topo-order --date-order --reverse - --no-merges + --no-merges --follow --abbrev-commit --abbrev= - --relative-date + --relative-date --date= --author= --committer= --grep= --all-match --pretty= --name-status --name-only --raw @@ -767,7 +808,7 @@ _git_config () case "$cur" in --*) __gitcomp " - --global --system + --global --system --file= --list --replace-all --get --get-all --get-regexp --add --unset --unset-all @@ -810,6 +851,7 @@ _git_config () core.ignoreStat core.preferSymlinkRefs core.logAllRefUpdates + core.loosecompression core.repositoryFormatVersion core.sharedRepository core.warnAmbiguousRefs @@ -841,6 +883,7 @@ _git_config () diff.renames fetch.unpackLimit format.headers + format.subjectprefix gitcvs.enabled gitcvs.logfile gitcvs.allbinary @@ -867,6 +910,10 @@ _git_config () merge.verbosity pack.window pack.depth + pack.windowMemory + pack.compression + pack.deltaCacheSize + pack.deltaCacheLimit pull.octopus pull.twohead repack.useDeltaBaseOffset @@ -977,6 +1024,31 @@ _git_stash () __gitcomp 'list show apply clear' } +_git_submodule () +{ + local i c=1 command + while [ $c -lt $COMP_CWORD ]; do + i="${COMP_WORDS[c]}" + case "$i" in + add|status|init|update) command="$i"; break ;; + esac + c=$((++c)) + done + + if [ $c -eq $COMP_CWORD -a -z "$command" ]; then + local cur="${COMP_WORDS[COMP_CWORD]}" + case "$cur" in + --*) + __gitcomp "--quiet --cached" + ;; + *) + __gitcomp "add status init update" + ;; + esac + return + fi +} + _git () { local i c=1 command __git_dir @@ -995,7 +1067,14 @@ _git () if [ $c -eq $COMP_CWORD -a -z "$command" ]; then case "${COMP_WORDS[COMP_CWORD]}" in --*=*) COMPREPLY=() ;; - --*) __gitcomp "--git-dir= --bare --version --exec-path" ;; + --*) __gitcomp " + --no-pager + --git-dir= + --bare + --version + --exec-path + " + ;; *) __gitcomp "$(__git_commands) $(__git_aliases)" ;; esac return @@ -1009,12 +1088,14 @@ _git () add) _git_add ;; apply) _git_apply ;; bisect) _git_bisect ;; + bundle) _git_bundle ;; branch) _git_branch ;; checkout) _git_checkout ;; cherry) _git_cherry ;; cherry-pick) _git_cherry_pick ;; commit) _git_commit ;; config) _git_config ;; + describe) _git_describe ;; diff) _git_diff ;; fetch) _git_fetch ;; format-patch) _git_format_patch ;; @@ -1034,6 +1115,7 @@ _git () show) _git_show ;; show-branch) _git_log ;; stash) _git_stash ;; + submodule) _git_submodule ;; whatchanged) _git_log ;; *) COMPREPLY=() ;; esac @@ -1057,10 +1139,12 @@ complete -o default -o nospace -F _git_am git-am complete -o default -o nospace -F _git_apply git-apply complete -o default -o nospace -F _git_bisect git-bisect complete -o default -o nospace -F _git_branch git-branch +complete -o default -o nospace -F _git_bundle git-bundle complete -o default -o nospace -F _git_checkout git-checkout complete -o default -o nospace -F _git_cherry git-cherry complete -o default -o nospace -F _git_cherry_pick git-cherry-pick complete -o default -o nospace -F _git_commit git-commit +complete -o default -o nospace -F _git_describe git-describe complete -o default -o nospace -F _git_diff git-diff complete -o default -o nospace -F _git_fetch git-fetch complete -o default -o nospace -F _git_format_patch git-format-patch @@ -1080,6 +1164,7 @@ complete -o default -o nospace -F _git_reset git-reset complete -o default -o nospace -F _git_shortlog git-shortlog complete -o default -o nospace -F _git_show git-show complete -o default -o nospace -F _git_stash git-stash +complete -o default -o nospace -F _git_submodule git-submodule complete -o default -o nospace -F _git_log git-show-branch complete -o default -o nospace -F _git_log git-whatchanged @@ -1092,7 +1177,9 @@ complete -o default -o nospace -F _git_add git-add.exe complete -o default -o nospace -F _git_apply git-apply.exe complete -o default -o nospace -F _git git.exe complete -o default -o nospace -F _git_branch git-branch.exe +complete -o default -o nospace -F _git_bundle git-bundle.exe complete -o default -o nospace -F _git_cherry git-cherry.exe +complete -o default -o nospace -F _git_describe git-describe.exe complete -o default -o nospace -F _git_diff git-diff.exe complete -o default -o nospace -F _git_format_patch git-format-patch.exe complete -o default -o nospace -F _git_log git-log.exe diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index be44e06c45..280557ecd4 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -99,47 +99,56 @@ if there is already one that displays the same directory." (defface git-status-face - '((((class color) (background light)) (:foreground "purple"))) + '((((class color) (background light)) (:foreground "purple")) + (((class color) (background dark)) (:foreground "salmon"))) "Git mode face used to highlight added and modified files." :group 'git) (defface git-unmerged-face - '((((class color) (background light)) (:foreground "red" :bold t))) + '((((class color) (background light)) (:foreground "red" :bold t)) + (((class color) (background dark)) (:foreground "red" :bold t))) "Git mode face used to highlight unmerged files." :group 'git) (defface git-unknown-face - '((((class color) (background light)) (:foreground "goldenrod" :bold t))) + '((((class color) (background light)) (:foreground "goldenrod" :bold t)) + (((class color) (background dark)) (:foreground "goldenrod" :bold t))) "Git mode face used to highlight unknown files." :group 'git) (defface git-uptodate-face - '((((class color) (background light)) (:foreground "grey60"))) + '((((class color) (background light)) (:foreground "grey60")) + (((class color) (background dark)) (:foreground "grey40"))) "Git mode face used to highlight up-to-date files." :group 'git) (defface git-ignored-face - '((((class color) (background light)) (:foreground "grey60"))) + '((((class color) (background light)) (:foreground "grey60")) + (((class color) (background dark)) (:foreground "grey40"))) "Git mode face used to highlight ignored files." :group 'git) (defface git-mark-face - '((((class color) (background light)) (:foreground "red" :bold t))) + '((((class color) (background light)) (:foreground "red" :bold t)) + (((class color) (background dark)) (:foreground "tomato" :bold t))) "Git mode face used for the file marks." :group 'git) (defface git-header-face - '((((class color) (background light)) (:foreground "blue"))) + '((((class color) (background light)) (:foreground "blue")) + (((class color) (background dark)) (:foreground "blue"))) "Git mode face used for commit headers." :group 'git) (defface git-separator-face - '((((class color) (background light)) (:foreground "brown"))) + '((((class color) (background light)) (:foreground "brown")) + (((class color) (background dark)) (:foreground "brown"))) "Git mode face used for commit separator." :group 'git) (defface git-permission-face - '((((class color) (background light)) (:foreground "green" :bold t))) + '((((class color) (background light)) (:foreground "green" :bold t)) + (((class color) (background dark)) (:foreground "green" :bold t))) "Git mode face used for permission changes." :group 'git) @@ -664,9 +673,11 @@ Return the list of files that haven't been handled." (ewoc-set-hf status (format "Directory: %s\nBranch: %s\nHead: %s%s\n" default-directory - (if (string-match "^refs/heads/" branch) - (substring branch (match-end 0)) - branch) + (if branch + (if (string-match "^refs/heads/" branch) + (substring branch (match-end 0)) + branch) + "none (detached HEAD)") head (if merge-heads (concat "\nMerging: " diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 6d0106237a..55778c5775 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -231,6 +231,56 @@ def findUpstreamBranchPoint(head = "HEAD"): return ["", settings] +def createOrUpdateBranchesFromOrigin(localRefPrefix = "refs/remotes/p4/", silent=True): + if not silent: + print ("Creating/updating branch(es) in %s based on origin branch(es)" + % localRefPrefix) + + originPrefix = "origin/p4/" + + for line in read_pipe_lines("git rev-parse --symbolic --remotes"): + line = line.strip() + if (not line.startswith(originPrefix)) or line.endswith("HEAD"): + continue + + headName = line[len(originPrefix):] + remoteHead = localRefPrefix + headName + originHead = line + + original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead)) + if (not original.has_key('depot-paths') + or not original.has_key('change')): + continue + + update = False + if not gitBranchExists(remoteHead): + if verbose: + print "creating %s" % remoteHead + update = True + else: + settings = extractSettingsGitLog(extractLogMessageFromGitCommit(remoteHead)) + if settings.has_key('change') > 0: + if settings['depot-paths'] == original['depot-paths']: + originP4Change = int(original['change']) + p4Change = int(settings['change']) + if originP4Change > p4Change: + print ("%s (%s) is newer than %s (%s). " + "Updating p4 branch from origin." + % (originHead, originP4Change, + remoteHead, p4Change)) + update = True + else: + print ("Ignoring: %s was imported from %s while " + "%s was imported from %s" + % (originHead, ','.join(original['depot-paths']), + remoteHead, ','.join(settings['depot-paths']))) + + if update: + system("git update-ref %s %s" % (remoteHead, originHead)) + +def originP4BranchesExist(): + return gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") + class Command: def __init__(self): self.usage = "usage: %prog [options]" @@ -1041,53 +1091,6 @@ class P4Sync(Command): for branch in branches.keys(): self.initialParents[self.refPrefix + branch] = branches[branch] - def createOrUpdateBranchesFromOrigin(self): - if not self.silent: - print ("Creating/updating branch(es) in %s based on origin branch(es)" - % self.refPrefix) - - originPrefix = "origin/p4/" - - for line in read_pipe_lines("git rev-parse --symbolic --remotes"): - line = line.strip() - if (not line.startswith(originPrefix)) or line.endswith("HEAD"): - continue - - headName = line[len(originPrefix):] - remoteHead = self.refPrefix + headName - originHead = line - - original = extractSettingsGitLog(extractLogMessageFromGitCommit(originHead)) - if (not original.has_key('depot-paths') - or not original.has_key('change')): - continue - - update = False - if not gitBranchExists(remoteHead): - if self.verbose: - print "creating %s" % remoteHead - update = True - else: - settings = extractSettingsGitLog(extractLogMessageFromGitCommit(remoteHead)) - if settings.has_key('change') > 0: - if settings['depot-paths'] == original['depot-paths']: - originP4Change = int(original['change']) - p4Change = int(settings['change']) - if originP4Change > p4Change: - print ("%s (%s) is newer than %s (%s). " - "Updating p4 branch from origin." - % (originHead, originP4Change, - remoteHead, p4Change)) - update = True - else: - print ("Ignoring: %s was imported from %s while " - "%s was imported from %s" - % (originHead, ','.join(original['depot-paths']), - remoteHead, ','.join(settings['depot-paths']))) - - if update: - system("git update-ref %s %s" % (remoteHead, originHead)) - def updateOptionDict(self, d): option_keys = {} if self.keepRepoPath: @@ -1108,7 +1111,7 @@ class P4Sync(Command): # map from branch depot path to parent branch self.knownBranches = {} self.initialParents = {} - self.hasOrigin = gitBranchExists("origin") or gitBranchExists("origin/p4") or gitBranchExists("origin/p4/master") + self.hasOrigin = originP4BranchesExist() if not self.syncWithOrigin: self.hasOrigin = False @@ -1128,14 +1131,14 @@ class P4Sync(Command): system("git update-ref %s refs/heads/p4" % self.branch) system("git branch -D p4"); # create it /after/ importing, when master exists - if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes: + if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch): system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) # TODO: should always look at previous commits, # merge with previous imports, if possible. if args == []: if self.hasOrigin: - self.createOrUpdateBranchesFromOrigin() + createOrUpdateBranchesFromOrigin(self.refPrefix, self.silent) self.listExistingP4GitBranches() if len(self.p4BranchesInGit) > 1: @@ -1518,6 +1521,9 @@ class P4Branches(Command): self.verbose = False def run(self, args): + if originP4BranchesExist(): + createOrUpdateBranchesFromOrigin() + cmdline = "git rev-parse --symbolic " cmdline += " --remotes" diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir index 3ff6bd166a..c6e154a84f 100755 --- a/contrib/workdir/git-new-workdir +++ b/contrib/workdir/git-new-workdir @@ -24,9 +24,21 @@ git_dir=$(cd "$orig_git" 2>/dev/null && git rev-parse --git-dir 2>/dev/null) || die "\"$orig_git\" is not a git repository!" -if test "$git_dir" = ".git" -then +case "$git_dir" in +.git) git_dir="$orig_git/.git" + ;; +.) + git_dir=$orig_git + ;; +esac + +# don't link to a configured bare repository +isbare=$(git --git-dir="$git_dir" config --bool --get core.bare) +if test ztrue = z$isbare +then + die "\"$git_dir\" has core.bare set to true," \ + " remove from \"$git_dir/config\" to use $0" fi # don't link to a workdir diff --git a/diff-delta.c b/diff-delta.c index 3af583536f..0dde2f2dc0 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -213,7 +213,7 @@ struct delta_index * create_delta_index(const void *buf, unsigned long bufsize) entry = hash[i]; do { struct index_entry *keep = entry; - int skip = hash_count[i] / HASH_LIMIT / 2; + int skip = hash_count[i] / HASH_LIMIT; do { entry = entry->next; } while(--skip && entry); diff --git a/diff.c b/diff.c index 6a99e0c84e..8a8bdf8bc3 100644 --- a/diff.c +++ b/diff.c @@ -2914,10 +2914,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) fill_mmfile(&mf2, p->two) < 0) return error("unable to read files to diff"); - /* Maybe hash p->two? into the patch id? */ - if (diff_filespec_is_binary(p->two)) - continue; - len1 = remove_space(p->one->path, strlen(p->one->path)); len2 = remove_space(p->two->path, strlen(p->two->path)); if (p->one->mode == 0) diff --git a/fast-import.c b/fast-import.c index 170cccdceb..078079d404 100644 --- a/fast-import.c +++ b/fast-import.c @@ -8,10 +8,11 @@ Format of STDIN stream: | new_tag | reset_branch | checkpoint + | progress ; new_blob ::= 'blob' lf - mark? + mark? file_content; file_content ::= data; @@ -23,7 +24,7 @@ Format of STDIN stream: ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)? ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)* file_change* - lf; + lf?; commit_msg ::= data; file_change ::= file_clr @@ -42,33 +43,36 @@ Format of STDIN stream: new_tag ::= 'tag' sp tag_str lf 'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf - 'tagger' sp name '<' email '>' when lf + 'tagger' sp name '<' email '>' when lf tag_msg; tag_msg ::= data; reset_branch ::= 'reset' sp ref_str lf ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)? - lf; + lf?; checkpoint ::= 'checkpoint' lf - lf; + lf?; + + progress ::= 'progress' sp not_lf* lf + lf?; # note: the first idnum in a stream should be 1 and subsequent # idnums should not have gaps between values as this will cause # the stream parser to reserve space for the gapped values. An - # idnum can be updated in the future to a new object by issuing + # idnum can be updated in the future to a new object by issuing # a new mark directive with the old idnum. - # + # mark ::= 'mark' sp idnum lf; data ::= (delimited_data | exact_data) - lf; + lf?; # note: delim may be any string but must not contain lf. # data_line may contain any data but must not be exactly # delim. delimited_data ::= 'data' sp '<<' delim lf (data_line lf)* - delim lf; + delim lf; # note: declen indicates the length of binary_data in bytes. # declen does not include the lf preceeding the binary data. @@ -78,10 +82,10 @@ Format of STDIN stream: # note: quoted strings are C-style quoting supporting \c for # common escapes of 'c' (e..g \n, \t, \\, \") or \nnn where nnn - # is the signed byte value in octal. Note that the only + # is the signed byte value in octal. Note that the only # characters which must actually be escaped to protect the # stream formatting is: \, " and LF. Otherwise these values - # are UTF8. + # are UTF8. # ref_str ::= ref; sha1exp_str ::= sha1exp; @@ -104,9 +108,9 @@ Format of STDIN stream: lf ::= # ASCII newline (LF) character; # note: a colon (':') must precede the numerical value assigned to - # an idnum. This is to distinguish it from a ref or tag name as + # an idnum. This is to distinguish it from a ref or tag name as # GIT does not permit ':' in ref or tag strings. - # + # idnum ::= ':' bigint; path ::= # GIT style file path, e.g. "a/b/c"; ref ::= # GIT ref name, e.g. "refs/heads/MOZ_GECKO_EXPERIMENT"; @@ -115,13 +119,24 @@ Format of STDIN stream: hexsha1 ::= # SHA1 in hexadecimal format; # note: name and email are UTF8 strings, however name must not - # contain '<' or lf and email must not contain any of the + # contain '<' or lf and email must not contain any of the # following: '<', '>', lf. - # + # name ::= # valid GIT author/committer name; email ::= # valid GIT author/committer email; ts ::= # time since the epoch in seconds, ascii base10 notation; tz ::= # GIT style timezone; + + # note: comments may appear anywhere in the input, except + # within a data command. Any form of the data command + # always escapes the related input from comment processing. + # + # In case it is not clear, the '#' that starts the comment + # must be the first character on that the line (an lf have + # preceeded it). + # + comment ::= '#' not_lf* lf; + not_lf ::= # Any byte that is not ASCII newline (LF); */ #include "builtin.h" @@ -254,6 +269,13 @@ typedef enum { WHENSPEC_NOW, } whenspec_type; +struct recent_command +{ + struct recent_command *prev; + struct recent_command *next; + char *buf; +}; + /* Configured limits on output */ static unsigned long max_depth = 10; static off_t max_packsize = (1LL << 32) - 1; @@ -319,9 +341,120 @@ static struct tag *last_tag; /* Input stream parsing */ static whenspec_type whenspec = WHENSPEC_RAW; static struct strbuf command_buf; +static int unread_command_buf; +static struct recent_command cmd_hist = {&cmd_hist, &cmd_hist, NULL}; +static struct recent_command *cmd_tail = &cmd_hist; +static struct recent_command *rc_free; +static unsigned int cmd_save = 100; static uintmax_t next_mark; static struct dbuf new_data; +static void write_branch_report(FILE *rpt, struct branch *b) +{ + fprintf(rpt, "%s:\n", b->name); + + fprintf(rpt, " status :"); + if (b->active) + fputs(" active", rpt); + if (b->branch_tree.tree) + fputs(" loaded", rpt); + if (is_null_sha1(b->branch_tree.versions[1].sha1)) + fputs(" dirty", rpt); + fputc('\n', rpt); + + fprintf(rpt, " tip commit : %s\n", sha1_to_hex(b->sha1)); + fprintf(rpt, " old tree : %s\n", sha1_to_hex(b->branch_tree.versions[0].sha1)); + fprintf(rpt, " cur tree : %s\n", sha1_to_hex(b->branch_tree.versions[1].sha1)); + fprintf(rpt, " commit clock: %" PRIuMAX "\n", b->last_commit); + + fputs(" last pack : ", rpt); + if (b->pack_id < MAX_PACK_ID) + fprintf(rpt, "%u", b->pack_id); + fputc('\n', rpt); + + fputc('\n', rpt); +} + +static void write_crash_report(const char *err) +{ + char *loc = git_path("fast_import_crash_%d", getpid()); + FILE *rpt = fopen(loc, "w"); + struct branch *b; + unsigned long lu; + struct recent_command *rc; + + if (!rpt) { + error("can't write crash report %s: %s", loc, strerror(errno)); + return; + } + + fprintf(stderr, "fast-import: dumping crash report to %s\n", loc); + + fprintf(rpt, "fast-import crash report:\n"); + fprintf(rpt, " fast-import process: %d\n", getpid()); + fprintf(rpt, " parent process : %d\n", getppid()); + fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_LOCAL)); + fputc('\n', rpt); + + fputs("fatal: ", rpt); + fputs(err, rpt); + fputc('\n', rpt); + + fputc('\n', rpt); + fputs("Most Recent Commands Before Crash\n", rpt); + fputs("---------------------------------\n", rpt); + for (rc = cmd_hist.next; rc != &cmd_hist; rc = rc->next) { + if (rc->next == &cmd_hist) + fputs("* ", rpt); + else + fputs(" ", rpt); + fputs(rc->buf, rpt); + fputc('\n', rpt); + } + + fputc('\n', rpt); + fputs("Active Branch LRU\n", rpt); + fputs("-----------------\n", rpt); + fprintf(rpt, " active_branches = %lu cur, %lu max\n", + cur_active_branches, + max_active_branches); + fputc('\n', rpt); + fputs(" pos clock name\n", rpt); + fputs(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", rpt); + for (b = active_branches, lu = 0; b; b = b->active_next_branch) + fprintf(rpt, " %2lu) %6" PRIuMAX" %s\n", + ++lu, b->last_commit, b->name); + + fputc('\n', rpt); + fputs("Inactive Branches\n", rpt); + fputs("-----------------\n", rpt); + for (lu = 0; lu < branch_table_sz; lu++) { + for (b = branch_table[lu]; b; b = b->table_next_branch) + write_branch_report(rpt, b); + } + + fputc('\n', rpt); + fputs("-------------------\n", rpt); + fputs("END OF CRASH REPORT\n", rpt); + fclose(rpt); +} + +static NORETURN void die_nicely(const char *err, va_list params) +{ + static int zombie; + char message[2 * PATH_MAX]; + + vsnprintf(message, sizeof(message), err, params); + fputs("fatal: ", stderr); + fputs(message, stderr); + fputc('\n', stderr); + + if (!zombie) { + zombie = 1; + write_crash_report(message); + } + exit(128); +} static void alloc_objects(unsigned int cnt) { @@ -524,8 +657,12 @@ static struct branch *new_branch(const char *name) if (b) die("Invalid attempt to create duplicate branch: %s", name); - if (check_ref_format(name)) + switch (check_ref_format(name)) { + case 0: break; /* its valid */ + case -2: break; /* valid, but too few '/', allow anyway */ + default: die("Branch name doesn't conform to GIT standards: %s", name); + } b = pool_calloc(1, sizeof(struct branch)); b->name = pool_strdup(name); @@ -1450,7 +1587,43 @@ static void dump_marks(void) static void read_next_command(void) { - read_line(&command_buf, stdin, '\n'); + do { + if (unread_command_buf) { + unread_command_buf = 0; + if (command_buf.eof) + return; + } else { + struct recent_command *rc; + + command_buf.buf = NULL; + read_line(&command_buf, stdin, '\n'); + if (command_buf.eof) + return; + + rc = rc_free; + if (rc) + rc_free = rc->next; + else { + rc = cmd_hist.next; + cmd_hist.next = rc->next; + cmd_hist.next->prev = &cmd_hist; + free(rc->buf); + } + + rc->buf = command_buf.buf; + rc->prev = cmd_tail; + rc->next = cmd_hist.prev; + rc->prev->next = rc; + cmd_tail = rc; + } + } while (command_buf.buf[0] == '#'); +} + +static void skip_optional_lf(void) +{ + int term_char = fgetc(stdin); + if (term_char != '\n' && term_char != EOF) + ungetc(term_char, stdin); } static void cmd_mark(void) @@ -1476,19 +1649,15 @@ static void *cmd_data (size_t *size) size_t sz = 8192, term_len = command_buf.len - 5 - 2; length = 0; buffer = xmalloc(sz); + command_buf.buf = NULL; for (;;) { - read_next_command(); + read_line(&command_buf, stdin, '\n'); if (command_buf.eof) die("EOF in data (terminator '%s' not found)", term); if (term_len == command_buf.len && !strcmp(term, command_buf.buf)) break; - if (sz < (length + command_buf.len)) { - sz = sz * 3 / 2 + 16; - if (sz < (length + command_buf.len)) - sz = length + command_buf.len; - buffer = xrealloc(buffer, sz); - } + ALLOC_GROW(buffer, length + command_buf.len, sz); memcpy(buffer + length, command_buf.buf, command_buf.len - 1); @@ -1510,9 +1679,7 @@ static void *cmd_data (size_t *size) } } - if (fgetc(stdin) != '\n') - die("An lf did not trail the binary data as expected."); - + skip_optional_lf(); *size = length; return buffer; } @@ -1808,13 +1975,13 @@ static void cmd_from_existing(struct branch *b) } } -static void cmd_from(struct branch *b) +static int cmd_from(struct branch *b) { const char *from; struct branch *s; if (prefixcmp(command_buf.buf, "from ")) - return; + return 0; if (b->branch_tree.tree) { release_tree_content_recursive(b->branch_tree.tree); @@ -1849,6 +2016,7 @@ static void cmd_from(struct branch *b) die("Invalid ref name or SHA1 expression: %s", from); read_next_command(); + return 1; } static struct hash_list *cmd_merge(unsigned int *count) @@ -1933,10 +2101,8 @@ static void cmd_new_commit(void) } /* file_change* */ - for (;;) { - if (1 == command_buf.len) - break; - else if (!prefixcmp(command_buf.buf, "M ")) + while (!command_buf.eof && command_buf.len > 1) { + if (!prefixcmp(command_buf.buf, "M ")) file_change_m(b); else if (!prefixcmp(command_buf.buf, "D ")) file_change_d(b); @@ -1946,8 +2112,10 @@ static void cmd_new_commit(void) file_change_cr(b, 0); else if (!strcmp("deleteall", command_buf.buf)) file_change_deleteall(b); - else - die("Unsupported file_change: %s", command_buf.buf); + else { + unread_command_buf = 1; + break; + } read_next_command(); } @@ -2088,7 +2256,8 @@ static void cmd_reset_branch(void) else b = new_branch(sp); read_next_command(); - cmd_from(b); + if (!cmd_from(b) && command_buf.len > 1) + unread_command_buf = 1; } static void cmd_checkpoint(void) @@ -2099,7 +2268,15 @@ static void cmd_checkpoint(void) dump_tags(); dump_marks(); } - read_next_command(); + skip_optional_lf(); +} + +static void cmd_progress(void) +{ + fwrite(command_buf.buf, 1, command_buf.len - 1, stdout); + fputc('\n', stdout); + fflush(stdout); + skip_optional_lf(); } static void import_marks(const char *input_file) @@ -2142,7 +2319,7 @@ static const char fast_import_usage[] = int main(int argc, const char **argv) { - int i, show_stats = 1; + unsigned int i, show_stats = 1; git_config(git_default_config); alloc_objects(object_entry_alloc); @@ -2196,8 +2373,14 @@ int main(int argc, const char **argv) if (i != argc) usage(fast_import_usage); + rc_free = pool_alloc(cmd_save * sizeof(*rc_free)); + for (i = 0; i < (cmd_save - 1); i++) + rc_free[i].next = &rc_free[i + 1]; + rc_free[cmd_save - 1].next = NULL; + prepare_packed_git(); start_packfile(); + set_die_routine(die_nicely); for (;;) { read_next_command(); if (command_buf.eof) @@ -2212,6 +2395,8 @@ int main(int argc, const char **argv) cmd_reset_branch(); else if (!strcmp("checkpoint", command_buf.buf)) cmd_checkpoint(); + else if (!prefixcmp(command_buf.buf, "progress ")) + cmd_progress(); else die("Unsupported command: %s", command_buf.buf); } diff --git a/git-am.sh b/git-am.sh index b5ed8ca15c..6809aa07f6 100755 --- a/git-am.sh +++ b/git-am.sh @@ -2,8 +2,10 @@ # # Copyright (c) 2005, 2006 Junio C Hamano -USAGE='[--signoff] [--dotest=] [--utf8 | --no-utf8] [--binary] [--3way] - [--interactive] [--whitespace=