{"thread":{"id":"2789","subject":"Re: as promised, docs: git for the confused","startedAt":"2005-12-09T05:43:04Z","lastAt":"2005-12-13T22:19:39Z","messageCount":28,"participants":["linux@horizon.com","Petr Baudis","Randy.Dunlap","Junio C Hamano","Linus Torvalds","Timo Hirvonen","Randal L. Schwartz","Joshua N Pritikin","H. Peter Anvin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"13402","messageId":"20051209054304.3908.qmail@science.horizon.com","threadId":"2789","inReplyTo":"7vbqzrcmgr.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2005-12-09T05:43:04Z","receivedAt":"2005-12-09T05:43:04Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"Thank you all for the comments.  I've tried to address them as follows:\n\njunkip@cox.net wrote:\n> I am unsure if we want to further confuse readers by saying\n> this, but technically, \"Likewise, a tag which is commit-ish can\n> be used in place of commit\".  Not all tags are necessarily\n> commit-ish.  v2.6.11 tag is tree-ish but not commit-ish for\n> example.  Typically, however, a tag is commit-ish.\n\nAh.  It makes me think of Ashford v. Thornton, but you're right, and worse\nyet, it's part of the kernel history.  (But Linus could still re-issue the\ntag and make it go away.  Are direct tags on trees considered desirable\nthese days?)\n\nhpa@zytor.com added:\n> Saying they can be used interchangably is just plain wrong, however. \n> It's not a bijective relation.\n\nI amended it to:\n\n+ The most common object needed by git primitives is a tree.  Since every\n+ commit or tag refers to a unique tree, both of these are acceptable\n+ \"tree-ish\" objects and can be used basically anywhere a tree is required.\n+ Likewise, a tag almost always refers to a commit, so is \"commit-ish\"\n+ and can be used where a commit is required.\n+ \n+ (I'd say a tag *always* points to a commit, but it's possible to tag\n+ a tree directly.  Probably the only time you will ever see this is\n+ the v2.6.11 tag in the Linux history, because git was still under\n+ heavy development and Linus was still making up the rules as he went\n+ along.)\n\nI wanted to keep the term \"tree-ish\", because it's actually widely\nused in the git documentation.\n\n\nalan@chandlerfamily.org.uk wrote:\n>> * Background material.\n>>\n>> To start with, read \"man git\".  Or Documentation/git.txt in the git\n>> source tree, which is the same thing.  Particularly note the description\n>> of the index, which is where all the action in git happens.\n>>\n>> One thing that's confusing is why git allows you to have one version of\n>> a file in the current HEAD, a second version in the index, and possibly a\n>> third in the working directory.  Why doesn't the index just contain a copy\n>> of the current HEAD until you commit a new one?  The answer is merging,\n>> which does all its work in the index.  Neither the object database nor\n>> the working directory let you have multiple files with the same name.\n>\n> If I was a complete newbie, I would be lost right here.  You start\n> refering to the term HEAD without any introduction to what it means and\n> (as far as I could see on a quick glance - which is what a newbie would\n> do - man git doesn't start out here either).\n> \n> If your audience really is a complete new commer, then as a minimum I\n> think you need  to describe to concept of a \"branch of development\" with\n> a series of snapshots of the state, the current of which is called HEAD.\n> You might even at this stage hint about there being several such branches.\n> The next bit, which goes on about the index is great - just put it into\n> context with a simple explanation first.\n\nFirst of all, this is a summary of what I found unclear *after* having\nread all the documentation, tutorials, etc. I could find.  The business\nof HEAD isn't that bad.\n\nI actually wrote a bunch of text explaining the usual basics, but\nthen realized that the existing docs did the job as well or better,\nand deleted it all.\n\nIf people think I should try to supplant the existing tutorials and\nkernel hacker's guides instead of supplementing them, I could try,\nbut I found them very good once I had the background to understand them.\n\nHowever, the comment is still valid: I don't introduce the term, and should.\n(Getting exposition out of order is a big hazard of cut-and-paste.)\n\nI've replaced that with:\n+ To start with, read \"man git\".  Or Documentation/git.txt in the git\n+ source tree, which is the same thing.  Particularly note the description\n+ of the index, which is where all the action in git happens.\n+ This document is to supplement that, not replace it.\n+ \n+ Like other version control systems, git has a current version (referred\n+ to as HEAD) in its object database, you make changes in the working\n+ directory, and then commit them, which appends a new version and makes\n+ that the new HEAD.\n+ \n+ However, there's also this \"index\" thing interposed.  As \"man git\"\n+ explains, you can have one version of the file in the HEAD, a second\n+ in the index, and a third in the working directory.  That's weird\n+ and confusing - why does git allow that?  Why isn't the index just an\n+ implementation detail that caches the HEAD until you commit a new one?\n+ \n+ The answer is merging, which does all its work in the index.  Being a\n+ toolkit, git has to pass partial merges around between its various\n+ tools, which means keeping track of multiple files all competing for\n+ the same name.  Neither the object database nor the working directory\n+ let you have multiple files with the same name.\n\nIs that any better?\n\n\nJosef.Weidendorfer@gmx.de wrote, about git-mv:\n> The nice thing about it is that you can move huge directories around,\n> or multiple files/dirs at once, and it will do the right thing. E.g.\n> \tgit-mv -k foo* bar/\n> will only move files which are version controlled.\n\nEr... this seems to require a mix of files where the version-controlled\nstatus is not defined by a naming convention.  Isn't that pretty unusual?\n\n> It is actually a 3-step process: rename, delete old, add new.\n> Perhaps it should be noted that this has nothing to do with any\n> explicit renaming feature like in other SCMs.\n\nThe \"delete old\" (from the index) part is taken care of by git-commit.\nI refer to the need to commit the old and new names, but a common\n\"git-commit -a\" will take care of that, and any other edits that\nhave been made in the meantime.\n\nAs I just added to the git-update-index description:\n+ \tA lot of early git documentation emphasizes this command,\n+ \tsince you need to have modified files in the index before you\n+ \tcan generate tree and commit objects.  But this is done by\n+ \tgit-commit, and you rarely want to invoke git-update-index\n+ \tdirectly any more.\n\n\nFinally, pasky@suse.de wrote:\n> That said, the \"git for the confused\" contains a lot of nice points, but\n> I don't think it's a good approach to just have extra document for\n> clarifying this stuff. It would be much better if the stock\n> documentation itself would not be confusing in the first place. Same\n> goes for the \"commands overview\" (BOUND to get out-of-date over time\n> since it's detached from the normal per-command documentation; we have\n> troubles huge enough to keep usage strings in sync, let alone the\n> manpages).\n\nI don't think it's the ideal solution either, but the idea of trying to\nsupplant Linus' tutorial is a bit alarming given my current still-novice\nstate.  I've been dabbling with git for a few weeks; many of the people\non this list have been using git in earnest for most of its life.\n\nUnfortunately, given the number of commands, you can't just document\nthem well individually.  Some overview of how they fit together into\na system is required.\n\nAs for keeping things in sync...\nThe problem with the usage strings and man pages is that they aim to\ndescribe everything, so omitting the latest minor feature is a bug.\nI'm not trying to document every detail of every command, just tell people\nenough that they can figure out which man page they should be reading.\nSurely the basic purpose of the existing commands isn't going to undergo\ntoo much more upheaval?\n\nI do confess some of the docs are rather dated.  One issue, that I just\nadded a paragraph about, is that they emphasize git-update-index a lot,\nwhile I think these days that's normally invoked via git-commit.\n"},{"id":"13403","messageId":"20051209054401.4016.qmail@science.horizon.com","threadId":"2789","inReplyTo":"7vbqzrcmgr.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2005-12-09T05:44:01Z","receivedAt":"2005-12-09T05:44:01Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"The revised version, with the changes previously noted.\n\n\nTODO: Describe the config file.  It's a recent invention, and I\nhaven't found a good description of its contents.\n\n\n\t\t\"I Don't Git It\"\n\t\tGit for the confused\n\nGit is hardly lacking in documentation, but coming at it fresh, I found\nit somewhat confusing.\n\nGit is a toolkit in the Unix tradition.  There are a number of primitives\nwritten in C, which are made friendly by a layer of shell scripts.\nThese are known in git-speak, as the \"plumbing\" and the \"porcelain\",\nrespectively.  The porcelain should work and look nice.  The plumbing\nshould just deal with lots of crap efficiently.\n\nMuch of git's documentation was first written to explain the plumbing to\nthe people writing the porcelain.  Since then, although the essentials\nhaven't changed, porcelain has been added and conventions have been\nestablished that make it a lot more pleasant to deal with.  Some commands\nhave been changed or replaced, and it's not quite the same.\n\nUsing the original low-level commands is now most likely more difficult\nthan necessary, unless you want to do something not supported by the\nexisting porcelain.\n\nThis document retraces (with fewer false turns) how I learned my way\naround git.  There are some concepts I didn't understand so well the\nfirst time through, and an overview of all the git commands, grouped\nby application.\n\n\nA good rule of thumb is that the commands with one-word names (git-diff,\ngit-commit, git-merge, git-push, git-pull, git-status, git-tag, etc.) are\ndesigned for end-user use.  Multi-word names (git-count-objects,\ngit-write-tree, git-update-index) are generally designed for use from\na script.\n\nThis isn't ironclad.  The first command to start using git is git-init-db,\nand git-show-branch is pure porcelain, while git-mktag is a primitive.\nAnd you don't often run git-daemon by hand.  But still, it's a useful\nguideline.\n\n\n\n* Background material.\n\nTo start with, read \"man git\".  Or Documentation/git.txt in the git\nsource tree, which is the same thing.  Particularly note the description\nof the index, which is where all the action in git happens.\nThis document is to supplement that, not replace it.\n\nLike other version control systems, git has a current version (referred\nto as HEAD) in its object database, you make changes in the working\ndirectory, and then commit them, which appends a new version and makes\nthat the new HEAD.\n\nHowever, there's also this \"index\" thing interposed.  As \"man git\"\nexplains, you can have one version of the file in the HEAD, a second\nin the index, and a third in the working directory.  That's weird\nand confusing - why does git allow that?  Why isn't the index just an\nimplementation detail that caches the HEAD until you commit a new one?\n\nThe answer is merging, which does all its work in the index.  Being a\ntoolkit, git has to pass partial merges around between its various\ntools, which means keeping track of multiple files all competing for\nthe same name.  Neither the object database nor the working directory\nlet you have multiple files with the same name.\n\nThe index is really very simple.  It's a series of structures, each\ndescribing one file.  There's an object ID (SHA1) of the contents,\nsome file metadata to detect changes (time-stamps, inode number, size,\npermissions, owner, etc.), and the path name relative to the root of the\nworking directory.  It's always stored sorted by path name, for efficient\nmerging.  By watching for metadata changes, git can efficiently detect\nthat a a file may have changed, and only open and examine those files.\n\nAt (almost) any time, you can take a snapshot of the index and write\nit as a tree object.\n\nThe only interesting feature is that each entry has a 2-bit stage number.\nNormally, this is always zero, but each path name is allowed up to three\ndifferent versions (object IDs) in the index at once.  This is used to\nrepresent an incomplete merge, and an unmerged index entry (with more\nthan one version) prevents committing the index to the object database.\n\n\nSome porcelain layers, such as cogito, work to hide the index and this\npotential confusion, but core git (shich is being described here) exposes\nit.\n\n\n* Terminology - heads, branches, refs, and revisions\n\n(This is a supplement to what's already in \"man git\".)\n\nThe most common object needed by git primitives is a tree.  Since every\ncommit or tag refers to a unique tree, both of these are acceptable\n\"tree-ish\" objects and can be used basically anywhere a tree is required.\nLikewise, a tag almost always refers to a commit, so is \"commit-ish\"\nand can be used where a commit is required.\n\n(I'd say a tag *always* points to a commit, but it's possible to tag\na tree directly.  Probably the only time you will ever see this is\nthe v2.6.11 tag in the Linux history, because git was still under\nheavy development and Linus was still making up the rules as he went\nalong.)\n\nAs soon as you get to the porcelain, the most commonly used object is\na commit.  Also known as a revision, this is a tree plus a history.\n\nWhile you can always use the full object ID, you can also use a reference.\nA reference is a file that contains a 40-character hex SHA1 object ID\n(and a trailing newline).  When you specify the name of a reference,\nit is searched for in one of the directories:\n\t.git/\t\t\t(or $GIT_DIR)\n\t.git/refs/\t\t(or $GIT_DIR/refs/)\n\t.git/refs/heads/\t(or $GIT_DIR/refs/heads/)\n\t.git/refs/tags/\t\t(or $GIT_DIR/refs/tags/)\n\nYou may use subdirectories by including slashes in the reference name.\nThere is no search order; if searching the above four path prefixes\nproduces more than one match for the reference name (it's ambiguous),\nthen the name is not valid.\n\nThere is additional syntax (which looks like \"commit~3^2~17\") for\nspecifying an ancestor of a given commit (or tag).  This is documented\nin detail in the documentation for git-rev-parse.  Briefly, commit^\nis the parent of the given commit.  commit^^ is the grandparent, etc..\nIf there is more than one ancestor (a merge), then they can be referenced\nas commit^1 (a synonym for commit^), commit^2, commit^3, etc.  (commit^0\ngives the commit object itself.  A no-op if you're starting from a commit,\nbut it lets you get the commit object from a tag object.)\n\nAs long strings of ^ can be annoying, they can be abbreviated using ~\nsyntax.  commit^^^ is the same as commit~3, ^^^^ is the same as ~4, etc.\nYou can see lots of examples in the output of \"git-show-branch\".\n\n\nNow, the although the most primitive git tools don't care, a convention\namong all the porcelain is that the current head of development is\n.git/HEAD, a symbolic link to a reference under refs/heads/.\n\ngit-init-db creates HEAD pointing to refs/heads/master, and that is\ntraditionally the name used for the \"main trunk\" of development.\nNote that initially refs/heads/master doesn't exist - HEAD is a\ndangling symlink!  This is okay, and will cause the initial commit\nto have zero parents.\n\nA \"head\" is mostly synonymous with a \"branch\", but the terms have\ndifferent emphasis.  The \"head\" is particularly the tip of the branch,\nwhere future development will be appended.  A \"branch\" is the entire\ndevelopment history leading to the head.  However, as far as git is\nconcerned, they're both references to commit objects, referred to from\nrefs/heads/.\n\nWhen you actually do more (with git-commit, or git-merge), then the\ncurrent HEAD reference is overwritten with the new commit's id, and\nthe old HEAD becomes HEAD^.  Since HEAD is a symlink, it's the file\nin refs/heads/ that's actually overwritten.  (See the git-update-ref\ndocumentation for further details.)\n\nThe git-checkout command actually changes the HEAD symlink.  git-checkout\nenforces the rule that it will only check out a branch under refs/heads.\nYou can use refs/tags as a source for git-diff or any other command that\nonly examines the revision, but if you want to check it out, you have\nto copy it to refs/heads.\n\n\n* The git command\n\nGit commands are generally separate executables or scripts, named with\na common \"git-\" prefix.  There's also a small wrapper called simply\n\"git\" which converts a command like \"git commit file.c\" into \"git-commit\nfile.c\".  This usage resembles CVS and many other version control systems.\n\nPeople vary in which form they prefer to use.  I use the git- prefixed\ncommands, because you have to ask for the man pages by those names,\nand you can get tab-completion of the command names in the shell.\n(With no special effort; yes, I know it can be done in many shells.)\n\nHowever, there are plans for change here.  Due to the large number of git\ncommands (many of which are helpers not designed for interactive use),\nthere have been complaints about the clutter in /usr/bin.  There has\nbeen motion towards putting the git-* commands in their own directory,\nto be invoked by the /usr/bin/git wrapper.\n\nIn this case, you'll have to leave out the initial hyphen, or add the\ngit binary directory to your $PATH.\n\n\n* Resetting\n\nThe \"undo\" command for commits to the object database is git-reset.\nLike all deletion-type commands, be careful or you'll hurt yourself.\nGiven a commit (using any of the syntaxes mentioned above), this\nsets the current HEAD to refer to the given commit.\n\nThis does NOT alter the HEAD symlink (as git-checkout <branch> will\ndo), but actually changes the reference pointed to by HEAD\n(e.g. refs/heads/master) to contain a new object ID.\n\nThe classic example is to undo an erroneous commit, use\n\"git-reset HEAD^\".\n\nThere are actually three kinds of git-reset:\ngit-reset --soft: Only overwrite the reference.  If you need to, you\n\tcan put everything back with a second git-reset --soft OLD_HEAD.\ngit-reset --mixed: This is the default, which I always think of as\n\t\"--medium\".  Overwrite the reference, and (using git-read-tree)\n\tread the commit into the index.  The working directory is unchanged.\ngit-reset --hard: Do everything --mixed does, and also check out the index\n\tinto the working directory, and delete any working directory\n\tfiles whose names were in the old version but not in the new.\n\tThis really erases all traces of the previous version.\n\nThe space taken up by the abandoned commit won't actually be\nreclaimed until you collect garbage with git-prune.\n\ngit-reset with no commit specified is \"git-reset HEAD\", which is much\nsafer because the object reference is not actually changed.  This can be\nused to undo changes in the index (or, with --hard, working directory)\nthat you did not intend.  Note, however, that it is not selective.\n\"git-checkout\" has options for doing this selectively.\n\nLike being sure what directory you're in when typing \"rm -r\", think\ncarefully about what branch you're on when typing \"git-reset <commit>\".\n\nThere is an undelete: git-reset stores the previous HEAD commit in\nOLD_HEAD.  And git-lost-found can find leftover commits until you do\na git-prune.\n\n\n* Merging\n\nMerging is central to git operations.  Indeed, a big difference between\ngit and other version control systems is that git assumes that a change\nwill be merged more often than it's written, as it's passed around\ndifferent developers' repositories.  Even \"git checkout\" is a specialized\nsort of merge.\n\nThe heart of merging is git-read-tree, but if you can understand it from\nthe man page, you're doing better than me.\n\nAs mentioned, the index and the working directory versions of a file\ncould both be different from the HEAD.  Git lets you merge \"under\" your\ncurrent working directory edits, as long as the merge doesn't change\nthe files you're editing.\n\nThere are some special cases of merging, but let me start with the\nprocedure for the general 3-way merge case: merging branch B into branch A\n(the current HEAD).\n\n1) Given two commits, find a common ancestor O to server as the origin\n   of the merge.  The basic \"resolve\" algorithm uses git-merge-base for\n   the task, but the \"recursive\" merge strategy gets more clever in the\n   case where there are multiple candidates.  I won't got into what it\n   does, but it does a pretty good job.\n\n2) Add all three input trees (the Origin, A, and B) to the index by\n   \"git-read-tree -m O A B\".  The index now contains up to three copies\n   of every file.  (Four, including the original, but that is discarded\n   before git-read-tree returns.)\n\n   Then, for each file in the index, git-read-tree does the following:\n\n   2a) For each file, git-merge-tree tries to collapse the various\n       versions into one using the \"trivial in-index merge\".  This just\n       uses the file blob object names to see if the file contents\n       are identical, and if two or more of the three trees contain an\n       identical copy of this file, it is merged.  A missing (deleted)\n       file matches another missing file.\n\n       Note that this is NOT a majority vote.  If A and B agree on the\n       contents of the file, that's what is used.  (Whether O agrees is\n       irrelevant in this case.)  But if O and A agree, then the change\n       made in B is taken as the final value.  Likewise, if O and B agree,\n       then A is used.\n\n   2b) If this is possible, then a check is made to see if the merge would\n       conflict with any uncommitted work in the index or change the index\n       out from under a modified working directory file.  If either of\n       those cases happen, the entire merge is backed out and fails.\n\n       (In the git source, the test \"t/t1000-read-tree-m-3way.sh\" has\n       a particularly detailed description of the various cases.)\n\n       If the merge is possible and safe, the versions are collapsed\n       into one final result version.\n\n   2c) If all three versions differ, the trivial in-index merge is\n       not possible, and the three source versions are left in the\n       index unmerged.  Again, if there was uncommitted work in the\n       index or the working directory, the entire merge fails.\n\n3) Use git-merge-index to iterate over the remaining unmerged files, and\n   apply an intra-file merge.  The intra-file merge is usually done with\n   git-merge-one-file, which does a standard RCS-style three-way merge\n   (see \"man merge\").\n\n4) Check out all the successfully merged files into the working directory.\n\n5) If automatic merging was successful on every file, commit the merged\n   version immediately and stop.\n\n6) If automatic merging was not complete, then replace the working\n   directory copies of any remaining unmerged files with a merged copy\n   with conflict markers (again, just like RCS or CVS) in the working\n   directory.  All three source versions are available in the index for\n   diffing against.\n\n   (We have not destroyed anything, because in step 2c), we checked to make\n   sure the working directory file didn't have anything not in the\n   repository.)\n\n7) Manually edit the conflicts and resolve the merge.  As long as an\n   unmerged, multi-version file exists in the index, committing the\n   index is forbidden.  (You can use the options to git-diff to\n   see the changes.)\n\n8) Commit the final merged version of the conflicting file(s), replacing\n   the unmerged versions with the single finished version.\n\nNote that if the merge is simple, with no one file edited on both\nbranches, git never has to open a single file.  It reads three tree\nobjects (recursively) and stat(2)s some working directory files to\nverify that they haven't changed.\n\nAlso note that this aborts and backs out rather than overwrite\nanything not committed.  You can merge \"under\" uncommitted edits\nonly if those edits are to files not affected by the merge.\n\nThere's one special case to the rule that \"you can't merge a file with\nuncommitted changes in the index\": if the changes match what the merge\nwould produce anyway (the patch from branch B has already been applied),\nthe merge succeeds.  There's no point in making you undo a change just\nso the merge can redo it.\n\n\n* 2-way merging\n\nThis merge is used by git-checkout to switch between two branches,\nwhile preserving any changes in the working directory and index.\n\nA \"2-way merge\" is actually a 3-way merge with the contents of the\nindex as the \"current HEAD\", and the original HEAD as the Origin.\nHowever, this merge is designed only for simple cases and only supports\nthe \"trivial merge\" cases.  It does not fall back to an intra-file merge.\n\nLike the 3-way case, if a particular file hasn't changed between\nthe previous and new two heads, then git will preserve any uncommitted\nedits, in both the index and the working directory.\n\nIf the file has changed in any way, git doesn't try to perform\nany sort of intra-file merge, it just fails.\n(Exception: like the 3-way merge, if the uncommitted change makes the\nfile the same as in the new head, the merge will succeed.)\n\n* 1-way merging\n\nThis is only used by git-reset, and is just an optimization over\nplain git-read-tree, but still it's interesting.\n\nPlain (non-merging) git-read-tree will overwrite the index entries with\nthose from the tree.  This invalidates the cached stat data, causing\ngit to think all the working directory files are \"potentially changed\"\nuntil you do a git-update-index --refresh.\n\nIn particular, this means that a subsequenct git-checkout-index,\nsuch as \"git-reset --hard\" performs, would overwrite every file\nin the working directory, even if only with a copy of itself,\ncausing a lot of extra work next time you run make.\n\nBy specifying a 1-way merge, any index entry whose contents (object ID)\nmatches the incoming tree will have its cached stat data preserved.\nThus, git will know if the working directory file is not changed, and\nwill not overwrite if you execute git-checkout-index.\n\nThis is just an efficiency hack, so it's not terribly important\nto remember.\n\n\n* Special merges - already up to date, and fast-forward\n\nThere are two cases of 3-way or 2-way merging that are special.\nRecall that the basic merge pattern is\n\n   B--------> A+B\n  /        /\n /        /\nO -----> A\n\nThe two special cases arise if one of A or B is a direct ancestor of\nthe other.  In that case, the common ancestor of both A and B is the\nolder of the two commits.  And the merged result is simply the\nnewer of the two, unchanged.\n\nRecalling that we are merging B into A, if B is a direct ancestor of A,\nthen A already includes all of B.  A is \"already up to date\" and not\nchanged at all by the merge.\n\nThe other case you'll hear mentioned, because it happens a lot when\npulling, is when A is a direct ancestor of B.  In this case, the\nresult of the merge is a \"fast-forward\" to B.\n\nBoth of these cases are handled very efficiently by the in-index merge\ndone by git-read-tree.\n\n\n* Deleted files during merges\n\nThere is one small wrinkle in git's merge algorithm that will probably\nnever bite you, but I ought to explain anyway, just because it's so rare\nthat it's difficult to discover it by experiment.\n\nThe index contains a list of all files that git is tracking.  If the\nindex file is empty or missing and you do a commit, you write an empty\ntree with no files.\n\nWhen merging, if git finds no pre-existing index entry for a path it is\ntrying to merge, it considers that to mean \"status unknown\" rather than\n\"modified by being deleted\".  Thus, this is not uncommitted work\nin the index file, and does not block the merge.  Instead, the\nfile will reappear in the merge.\n\nThis is because it is possible to blow away the index file (rm .git/index\nwill do it quite nicely), and if this was considered a modification to\nbe preserved, it would cause all sorts of conflicts.\n\nSo the one change to the index that will NOT be preserved by a merge is\nthe removal of a file.  A missing index entry is treated the same as an\nunmodified index entry.  The index will be updated, and when you check\nout the revision, the working directory file will be (re-)created.\n\nNote that none of this affects you in the usual case where you make\nchanges in the working directory only, and leave the index equal to HEAD\nuntil you're ready to commit.\n\n\n* Packs\n\nOriginally, git stored every object in its own file, and used rsync\nto share repositories.  It was quickly discovered that this brought\nmighty servers to their knees.  It's great for retrieving a small\nsubset of the database the way git usually does, but rsync scans the\nwhole .git/objects tree every time.\n\nSo packs were developed.  A pack is a file, built all at once, which\ncontains many delta-compressed objects.  With each .pack file,\nthere's an accompanying .idx file that indexes the pack so that\nindividual objects can be retrieved quickly.\n\nYou can reduce the disk space used by your repositories by periodically\nrepacking them with git-repack.  Normally, this makes a new incremental\npack of everything not already packed.  With the -a flag, this repacks\neverything for even greater compression (but takes longer).\n\nThe git wire protocol basically consists of negotiation over what\nobjects needs to be transferred followed by sending a custom-built pack.\nThe .idx file can be reconstructed from the .pack file, so it's\nnever transferred.\n\n[[ Is once every few hundred commits a good rule of thumb for repacking?\nWhen .git/objects/?? reaches X megabytes?  I think too many packs is\nitself a bad thing, since they all have to be searched. ]]\n\n\n* Raw diffs\n\nA major source of git's speed is that it tries to avoid accessing files\nunnecessarily.  In particular, files can be compared based on their\nobject IDs without needing to open and read them.  As part of this,\nthe responsibility for finding file differences (printing diffs) is\ndivided into finding what files have changed, and finding the changes\nwithin those files.\n\nThis is all explained in the Documentation/diffcore.txt in the git\ndistribution, but the basics is that many of the primitives spit out a\nline like this:\n:100755 100755 68838f3fad1d22ab4f14977434e9ce73365fb304 0000000000000000000000000000000000000000 M\tgit-bisect.sh\nwhen asked for a diff.  This is known as a \"raw diff\".  They can be\ntold to generate a human-readable diff with the \"-p\" (patch) flag.\nThe git-diff command includes this by default.\n\n\n* Advice on using git\n\nIf you're used to CVS, where branches and merges are \"advanced\" features\nthat you can go a long time, you need to learn to use branches in git a\nlot more.  Branch early and often.  Every time you think about developing\na feature or fixing a bug, create a branch to do it on.\n\nIn fact, avoid doing any development on the master branch.  Merges only.\n\nA branch is the git equivalent of a patch, and merging a branch is the\nequivalent of applying that patch.  A branch gives it a name that\nyou can use to refer to it.  This is particularly useful if you're\nsharing your changes.\n\nOnce you're done with a branch, you can delete it.  This is basically\njust removing the refs/heads/<branch> file, but \"git-branch -d\" adds a\nfew extra safety checks.  Assuming you merged the branch in, you can\nstill find all the commits in the history, it's just the name that's\nbeen deleted.\n\nYou can also rename a branch by renaming the refs/heads/branch file.\nThere's no git command to do this, but as long as you update\nthe HEAD symlink if necessary, you don't need one.\n\nPeriodically merge all of the branches you're working on into a testing\nbranch to see if everything works.  Blow away and re-create the\ntesting branch whenever you do this.  When you like the result,\nmerge them into the master.\n\n\n* The .git directory\n\nThere are a number of files in the .git directory used by the\nporcelain.  In case you're curious (I was), this is what they are:\n\nindex\n- The actual index file.\n\nobjects/\n- The object database.  Can be overridden by $GIT_OBJECT_DIRECTORY\n\nhooks/\n- where the hook scripts are kept.  The standard git template includes\n  examples, but disabled by being marked non-executable.\n\ninfo/exclude\n- Default project-wide list of file patterns to exclude from notice.\n  To this is added the per-directory list in .gitignore.\n  See the git-ls-files docs for full details.\n\nrefs/\n- References to development heads (branches) and tags.\n\nremotes/\n- Short names of remote repositories we pull from or push to.\n  Details are in the \"git-fetch\" man page.\n\nHEAD\n- The current default development head.\n- Created by git-init-db and never deleted\n- Changed by git-checkout\n- Used by git-commit and any other command that commits changes.\n- May be a dangling pointer, in which case git-commit\n  does an \"initial checkin\" with no parent.\n\nCOMMIT_EDITMSG\n- Temp used by git-commit to edit a commit message.\nCOMMIT_MSG\n- Temp used by git-commit to form a commit message,\n  post-processed from COMMIT_EDITMSG.\n\nFETCH_HEAD\n- Just-fetched commits, to be merged into the local trunk.\n- Created by git-fetch.\n- Used by git-pull as the source of data to merge.\n\nMERGE_HEAD\n- Keeps track of what heads are currently being merged into HEAD.\n- Created by git-merge --no-commit with the heads used \n- Deleted by git-checkout and git-reset (since you're abandoning\n  the merge)\n- Used by git-commit to supply additional parents to the current commit.\n  (And deleted when done.)\n\nMERGE_MSG\n- Generated by git-merge --no-commit.\n- Used by git-commit as the commit message for a merge\n  (If present, git-commit doesn't prompt.)\n\nMERGE_SAVE\n- cpio archive of all locally modified files created by\n  \"git-merge\" before starting to do anything, if multiple\n  merge strategies are being attempted.\n  Used to rewind the tree in case a merge fails.\n\nORIG_HEAD\n- Previous HEAD commit prior to a merge or reset operation.\n\nLAST_MERGE\n- Set by the \"resolve\" strategy to the most recently merged-in branch.\n  Basically, a copy of MERGE_HEAD.  Not used by the other merge strategies,\n  and resolve is no longer the default, so its utility is very limited.\n\nBISECT_LOG\n- History of a git-bisect operation.\n- Can be replayed (or, more usefully, a prefix can) by \"git-bisect replay\"\nBISECT_NAMES\n- The list of files to be modified by git-bisect.\n- Set by \"git-bisect start\"\n\nTMP_HEAD (used by git-fetch)\nTMP_ALT (used by git-fetch)\n\n\n* Git command summary\n\nThere are slightly over a hundred git commands.  This section tries to\nclassify them by purpose, so you can know which commands are intended to\nbe used for what.  You can always use the low-level plumbing directly,\nbut that's inconvenient and error-prone.\n\nHelper programs (not for direct use) for a specific utility are shown\nindented under the program they help.\n\nNote that all of these can be invoked using the \"git\" wrapper by replacing\nthe leading \"git-\" with \"git \".  The results are exactly the same.\nThere is a suggestion to reduce the clutter in /usr/bin and move all\nthe git binaries to their own directory, leaving just the git wrapper\nin /usr/bin. so you'll have to use it or adjust your $PATH.  But that\nhasn't happened yet.  In the meantime, including the hyphen makes\ntab-completion work.\n\nI include \".sh\", \".perl\", etc. suffixes to show what the programs are\nwritten in, so you can read those scripts written in languages you're\nfamiliar with.  These are the names in the git source tree, but the\nsuffix is not included in the /usr/bin copies.\n\n+ Administrative commands\ngit-init-db\n\n+ Object database maintenance:\ngit-convert-objects\ngit-fsck-objects\ngit-lost-found.sh\ngit-prune.sh\ngit-relink.perl\n\n+ Pack maintenance\ngit-count-objects.sh\ngit-index-pack\ngit-pack-objects\ngit-pack-redundant\ngit-prune-packed\ngit-repack.sh\ngit-show-index\ngit-unpack-objects\ngit-verify-pack\n\n+ Important primitives\ngit-commit-tree\ngit-rev-list\ngit-rev-parse\n\n+ Useful primitives\ngit-ls-files\ngit-update-index\n\n+ General script helpers (used only by scripts)\ngit-cat-file\ngit-check-ref-format\ngit-checkout-index\ngit-fmt-merge-msg.perl\ngit-hash-object\ngit-ls-tree\ngit-repo-config\ngit-unpack-file\ngit-update-ref\ngit-sh-setup.sh\ngit-stripspace\ngit-symbolic-ref\ngit-var\ngit-write-tree\n\n+ Oddballs\ngit-mv.perl\n\n+ Code browsing\ngit-diff.sh\n  git-diff-files\n  git-diff-index\n  git-diff-tree\n  git-diff-stages\ngit-grep.sh\ngit-log.sh\ngit-name-rev\ngit-shortlog.perl\ngit-show-branch\ngit-whatchanged.sh\n\n+ Making local changes\ngit-add.sh\ngit-bisect.sh\ngit-branch.sh\ngit-checkout.sh\ngit-commit.sh\ngit-reset.sh\ngit-status.sh\n\n+ Cherry-picking\ngit-cherry.sh\n  git-patch-id\ngit-cherry-pick.sh\ngit-rebase.sh\ngit-revert.sh\n\n+ Accepting changes by e-mail\ngit-apply\ngit-am.sh\n  git-mailinfo\n  git-mailsplit\n  git-applypatch.sh\ngit-applymbox.sh\n\n+ Publishing changes by e-mail\ngit-format-patch.sh\ngit-send-email.perl\n\n+ Merging\ngit-merge.sh\n  git-merge-base\n  git-merge-index\n    git-merge-one-file.sh\n  git-merge-octopus.sh\n  git-merge-ours.sh\n  git-merge-recursive.py\n  git-merge-resolve.sh\n  git-merge-stupid.sh\ngit-read-tree\ngit-resolve.sh\ngit-octopus.sh\n\n+ Making releases\ngit-get-tar-commit-id\ngit-tag.sh\n  git-mktag\ngit-tar-tree\ngit-verify-tag.sh\n\n+ Accepting changes by network\ngit-clone.sh\n  git-clone-pack\ngit-fetch.sh\n  git-fetch-pack\n  git-local-fetch\n  git-http-fetch\n  git-ssh-fetch\ngit-ls-remote.sh\n  git-peek-remote\ngit-parse-remote.sh\ngit-pull.sh\n  git-ssh-pull\ngit-shell\n  git-receive-pack\n\n+ Publishing changes by network\ngit-daemon\n\ngit-push.sh\n  git-http-push\n  git-ssh-push\n  git-ssh-upload\ngit-request-pull.sh\ngit-send-pack\ngit-update-server-info\ngit-upload-pack\n\nAll of the basic git commands are designed to be scripted.  When\nscripting, use the \"--\" option to ensure that files beginning with\n\"-\" won't be interpreted as options, and the \"-z\" option to output\nNUL-terminated file names so embedded newlines won't break things.\n\n(A person who'd do either of these on purpose is probably crazy, but\nit's not actually illegal.)\n\nLooking at existing shell scripts can be very informative.\n\n\n\n* Detailed list\n\nHere's a repeat, including descriptions.  I don't try to include\nevery detail you can find on the man page, but to explain when\nyou'd want to use a command.\n\n+ Administrative commands\ngit-init-db\n\tThis creates an empty git repository in ./.git (or $GIT_DIR if\n\tthat is non-null) using a system-wide template.\n\tIt won't hurt an existing repository.\n\n+ Object database maintenance:\ngit-convert-objects\n\tYou will *never* need to use this command.\n\tThe git repository format has undergone some revision since its\n\tfirst release.  If you have an ancient and crufty git repository\n\tfrom the very very early days, this will convert it for you.\n\tBut as you're new to git, it doesn't apply.\ngit-fsck-objects\n\tValidate the object database.  Checks that all references\n\tpoint somewhere, all the SHA1 hashes are correct, and that\n\tsort of thing.\n\n\tThis walks the entire repository, uncompressing and hashing\n\tevery object, so it takes a while.  Note that by default,\n\tit skips over packs, which can make it seem misleadingly fast.\ngit-lost-found.sh\n\tFind (using git-fsck-objects) any unreferenced commits and\n\ttags in the object database, and place them in a .git/lost-found\n\tdirectory.  This can be used to recover from accidentally\n\tdeleting a tag or branch reference that you wanted to keep.\n\n\tThis is the opposite of git-prune.\ngit-prune.sh\n\tDelete all unreachable objects from the object database.\n\tIt deletes useless packs, but does not remove useless\n\tobjects from the middle of partially useful packs.\n\n\tGit leaks objects in a number of cases, such as unsuccessful\n\tmerges.  The leak rate is generally a small fraction of\n\tthe rate at which the desired history grows, so it's not\n\tvery alarming, but occasionally running git-prune will\n\teliminate the \n\n\tIf you deliberately throw away a development branch, you\n\twill need to run this command to fully reclaim the disk space.\n\n\tOn something like the full Linux repository, this takes\n\ta while.\ngit-relink.perl\n\tMerge the objects stores of multiple git repositories by\n\tmaking hard links between them.  Useful to save space if\n\tduplicate copies are accidentally created on one machine.\n\n+ Pack maintenance\n\tThe classic git format is to compress and store each object\n\tseparately.  This is still used for all newly created changes.\n\tHowever, objects can also be stored en masse in \"packs\" which\n\tcontain many objects and tan take advantage of delta-compressing.\n\tRepacking your repositories periodically can save space.\n\t(Repacking is pretty quick but not quick enough to be\n\tcomfortable doing every commit.)\ngit-count-objects.sh\n\tPrint the number and total size of unpacked objects in the\n\trepository, to help you decide when is a good time to repack.\ngit-index-pack\n\tA pack file has an accompanying .idx file to allow rapid lookup.\n\tThis regenerates the .idx file from the .pack.  This is almost never\n\tneeded directly, but can be used after transferring a .pack file\n\tbetween machines.\ngit-pack-objects\n\tGiven a list of objects on stdin, build a pack file.  This is\n\ta helper used by the various network communication scripts.\ngit-pack-redundant\n\tProduce a list of redundant packs, for feeding to \"xargs rm\".\n\tA helper for git-prune.\ngit-prune-packed\n\tDelete unpacked object files that are duplicated in packs.\n\t(With -n, only lists them.)  A helper for git-prune.\ngit-repack.sh\n\tMake a new pack with all the unpacked objects.\n\tWith -a, include already-packed objects in the new pack.\n\tWith -d as well, deletes all the old packs thereby made redundant.\ngit-show-index\n\tDump the contents of a pack's .idx file.  Mostly for\n\tdebugging git itself.\ngit-unpack-objects\n\tUnpack a .pack file, the opposite of git-pack-objects.\tWith -n,\n\tdoesn't actually create the files.  With -q, suppresses the\n\tprogress indicator.\ngit-verify-pack\n\tValidate a pack file.  Useful when debugging git, and when\n\tdownloading from a remote source.  A helper for git-clone.\n\n+ Important primitives\n\tAlthough these primitives are not used directly very frequently,\n\tunderstanding them will help you understand other git commands\n\tthat wrap them.\ngit-commit-tree\n\tCreate a new commit object from a tree and a list of parent\n\tcommits.  This is the primitive that's the heart of git-commit.\n\t(It's also used by git-am, git-applypatch, git-merge, etc.)\ngit-rev-list\n\tPrint a list of commits (revisions), in reverse chronological\n\torder.  This is the heart of git-log and other history examination\n\tcommands, and the options for specifying parts of history are\n\tshared by all of them.\n\n\tIn particular, it takes an arbitrary number of revisions as\n\targuments, some of which may be prefixed with ^ to negate them.\n\tThese make up \"include\" and \"exclude\" sets.  git-rev-list\n\tlists all revisions that are ancestors of the \"include\" set\n\tbut not ancestors of the \"exclude\" set.\n\t\n\tFor this purpose, a revision is considered an ancestor of itself.\n\tThus, \"git-rev-list ^v1.1 v1.2\" will list all revisions from\n\tthe v1.2 release back to (but not including) the v1.1 release.\n\n\tBecause this is so convenient, a special syntax, \"v1.1..v1.2\"\n\tis allowed as an equivalent.  However, occasionally the general\n\tform is useful.  For example, adding ^branch will show the trunk\n\t(including merges from the branch), but exclude the branch itself.\n\n\tSimilarly, \"branch ^trunk\", a.k.a. trunk..branch, will show\n\tall work on the branch that hasn't been merged to the trunk.\n\tThis works even though trunk is not a direct ancestor of branch.\n\t\n\tGit-rev-list has a variety of flags to control it output format.\n\tThe default is to just print the raw SHA1 object IDs of the\n\tcommits, but --pretty produces a human-readable log.\n\n\tYou can also specify a set of files names (or directories),\n\tin which case output will be limited to commits that modified\n\tthose files.\n\n\tThis command is used extensively by the git:// protocol to compute\n\ta set of objects to send to update a repository.\ngit-rev-parse\n\tThis is a very widely used command line canonicalizer for git\n\tscripts.  It converts relative commit references (e.g. master~3)\n\tto absolute SHA1 hashes, and can also pass through arguments\n\tnot recognizable as references, so the script can interpret them.\n\n\tIt is important because it defines the <rev> syntax.\n\n\tThis takes a variety of options to specify how to prepare the\n\tcommand line for the script's use.  --verify is a particularly\n\timportant one.\n\n+ Useful primitives\n\tThese primitives are potentially useful directly.\ngit-ls-files\n\tList files in the index and/or working directory.  A variety of\n\toptions control which files to list, based on whether they\n\tare the same in both places or have been modified.  This command\n\tis the start of most check-in scripts.\ngit-update-index\n\tCopy the given files from the working directory into the index.\n\tThis create the blob objects, but no trees yet.  (Note that\n\tediting a file executing this multiple times without creating a\n\tcommit will generate orphaned objects.  Harmless.)\n\n\tA lot of early git documentation emphasizes this command,\n\tsince you need to have modified files in the index before you\n\tcan generate tree and commit objects.  But this is done by\n\tgit-commit, and you rarely want to invoke git-update-index\n\tdirectly any more.\n\n\tOne common safe option is \"git-update-index --refresh\".  This\n\tlooks for files whose metadata (modification time etc.) has\n\tchanged, but not their contents, and updates the metadata in the\n\tindex so the file contents won't have to be examined again.\n\n+ General script helpers (used only by scripts)\n\tThese are almost exclusively helpers for use in porcelain\n\tscripts and have little use by themselves from the command line.\ngit-cat-file\n\tExtract a file from the object database.  You can ask for\n\tan object's type or size given only an object ID, but\n\tto get its contents, you have to specify the type.  This\n\tis a deliberate safety measure.\ngit-check-ref-format\n\tVerify that the reference specified on the command line is\n\tsyntactically valid for a new reference name under $GIT_DIR/refs.\n\tA number of characters (^, ~, :, and ..) are reserved; see the man\n\tpage for the full list of rules.\ngit-checkout-index\n\tCopy files from the index to the working directory, or to a\n\tspecified directory.  Most important as a helper for git-checkout,\n\tthis is also used by git-merge and git-reset.\ngit-fmt-merge-msg.perl\n\tGenerate a reasonable default commit message for a merge.\n\tUsed by git-pull and git-octopus.\ngit-hash-object\n\tVery primitive helper to turn an arbitrary file into an object,\n\treturning just the ID or actually adding it to the database.\n\tUsed by the cvs-to-git and svn-to-git import filters.\ngit-ls-tree\n\tList the contents of a tree object.  Will tell you all the files\n\tin a commit.  Used by the checkout scripts git-checkout and git-reset.\ngit-repo-config\n\tGet and set options in .git/config.  The .git/config format\n\tis designed to be human-readable.  This gives programmatic\n\taccess to the settings.  This currently has a lot of overlap\n\twith the function of git-var.\ngit-unpack-file\n\tWrite the contents of the given block to a temporary file,\n\tand return the name of that temp file.  Used most often\n\tby merging scripts.\ngit-update-ref\n\tRewrite a reference (in .git/refs/) to point to a new object.\n\t\"echo $sha1 > $file\" is mostly equivalent, but this adds locking\n\tso two people don't update the same reference at once.\ngit-sh-setup.sh\n\tThis is a general prefix script that sets up\n\t$GIT_DIR and $GIT_OBJECT_DIRECTORY for a script,\n\tor errors out if the git control files can't be found.\ngit-stripspace\n\tRemove unnecessary whitespace.  Used mostly on commit messages\n\treceived by e-mail.\ngit-symbolic-ref\n\tThis queries or creates symlinks to references such as HEAD.\n\tBasically equivalent to readlink(1) or ln -s, this also works\n\ton platforms that don't have symlinks.  See the man page.\ngit-var\n\tProvide access to the GIT_AUTHOR_IDENT and/or GIT_COMMITTER_IDENT\n\tvalues, used in various commit scripts.  This currently has a\n\tlot of overlap with the function of git-repo-config.\ngit-write-tree\n\tGenerate a tree object reflecting the current index.  The output\n\tis the tree object; if you don't remember it somewhere (usually,\n\tpass it to git-commit-tree), it'll be lost.\n\n\tThis requires that the index be fully merged.  If any incomplete\n\tmerges are present in the index (files in stages 1, 2 or 3),\n\tgit-write-tree will fail.\n\n+ Oddballs\ngit-mv.perl\n\tI have to admit, I'm not quite sure what great advantages this is\n\tsupposed to have over plain \"mv\" followed by \"git-update-index\",\n\tor why it's complex enough to need perl.\n\n\tBasically, this renames a file, deleting its old name and adding\n\tits new name to the index.  Git doesn't have the concept of a\n\tpermanent file ID tracked across renames, so there's no need to\n\tuse a special tool, but it is a two-step process to rename a file:\n\t- Rename the file\n\t- git-add the new name\n\tFollowed by which you must commit both the old and new names.\n\n\tI suppose if you have a mixture of version-controlled and\n\tnon-version-controlled files with similar names, the fact that\n\tgit-mv knows not to touch the latter could be useful.\n\n+ Code browsing\ngit-diff.sh\n\tShow changes between various trees.  Takes up to two tree\n\tspecifications, and shows the difference between the versions.\n\tZero arguments: index vs. working directory (git-diff-files)\n\tOne: tree vs. working directory (git-diff-index)\n\tOne, --cached: tree vs. index (git-diff-index)\n\tTwo: tree vs. tree (git-diff-tree)\n\n\tThis wrapper always produces human-readable patch output.\n\tThe helpers all produce \"diff-raw\" format unless you supply\n\tthe -p option.\n\n\tThere are some interesting options.  Unfortunately, the git-diff\n\tman page is annoyingly sparse, and refers to the helper scripts'\n\tdocumentation rather than describing the many useful options\n\tthey all have in common.  Please do read the man pages of the\n\thelpers to see what's available.\n\t\n\tIn particular, although git does not explicitly record file\n\trenames, it has some pretty good heuristics to notice things.\n\t-M tries to detect renamed files by matching up deleted files\n\twith similar newly created files.  -C tries to detect copies\n\tas well.  By default, -C only looks among the modified files for\n\tthe copy source.  For common cases like splitting a file in two,\n\tthis works well.  The --find-copies-harder searches ALL files\n\tin the tree for the copy source.  This can be slow on large trees!\n\n\tSee Documentation/diffcore.txt for an explanation of how all\n\tthis works.\n  git-diff-files\n\tCompare the index and the working directory.\n  git-diff-index\n\tCompare the working directory and a given tree.  This is the\n\tgit equivalent of the single-operand form of \"cvs diff\".\n\tIf \"--cached\" is specified, uses the index rather than the working\n\tdirectory.\n  git-diff-tree\n\tCompare two trees.  This is the git equivalent of the two-operand\n\tform of \"cvs diff\".  This command is sometimes useful by itself\n\tto see the changes made by a single commit.  If you give it\n\tonly one commit on the command line, it shows the diff between\n\tthat commit and its first parent.  If the commit specification\n\tis long and awkward to type, using \"git-diff-tree -p <commit>\"\n\tcan be easier than \"git-diff <commit>^ <commit>\".\n  git-diff-stages\n\tAlthough not called by git-diff, there is a fourth diff helper\n\troutine, used to compare the various versions of an unmerged\n\tfile in the index.  It is intended for use by merging porcelain.\ngit-grep.sh\n\tA very simple wrapper that runs git-ls-files and greps the\n\toutput looking for a file name.  Does nothing fancy except\n\tsaves typing.\ngit-log.sh\n\tWrapper around git-rev-list --pretty.  Shows a history\n\tof changes made to the repository.  Takes all of git-rev-list's\n\toptions for specifying which revisions to list.\ngit-name-rev\n\tFind a symbolic name for the commit specified on the\n\tcommand line, and returns a symbolic name of the form\n\t\"maint~404^2~7\".  Basically, this does a breadth-first search\n\tfrom all the heads in .git/refs looking for the given commit.\ngit-shortlog.perl\n\tThis is a filter for the output of \"git-log --pretty=short\"\n\tto generate a one-line-per-change \"shortlog\" as Linus likes.\ngit-show-branch\n\tVisually show the merge history of the references given as\n\targuments.  Prints one column per reference and one line per\n\tcommit showing whether that commit is an ancestor of each\n\treference.\ngit-whatchanged.sh\n\tA simple wrapper around git-rev-list and git-diff-tree,\n\tthis shows the change history of a repository.  Specify a\n\tdirectory or file on the command line to limit the\n\toutput to changes affecting those files.  This isn't\n\tthe same as \"cvs annotate\", but it serves a similar purpose\n\tamong git folks.\n\n\tYou can add the -p option to include patches as well as log\n\tcomments.  You can also add the -M or -C option to follow\n\thistory back through file renames.\n\n\t-S is interesting: it's the \"pickaxe\" option.  Given a string,\n\tthis limits the output to changes that make that string appear\n\tor disappear.  This is for \"digging through history\" to see when\n\ta piece of code was introduced.  The string may (and often does)\n\tcontain embedded newlines.  See Documentation/cvs-migration.txt.\n\n+ Making local changes\n\tAll of these are examples of \"porcelain\" scripts.  Reading the\n\tscripts themselves can be informative; they're generally not\n\ttoo confusing.\ngit-add.sh\n\tA simple wrapper around \"git-ls-files | git-update-index --add\"\n\tto add new files to the index.   You may specify directories.\n\tYou need to invoke this for every new file you want git to\n\ttrack.\ngit-bisect.sh\n\tUtility to do a binary search to find the change that broke something.\n\tThe heart of this is in \"git-rev-list --bisect\"\n\tA very handy little utility!  Kernel developers love it\n\twhen you tell them exactly which patch broke something.\n\tNOTE: this uses the head named \"bisect\", and will blow\n\taway any existing branch by that name.  Try not to\n\tcreate a branch with that name.\n\n\tThere are three steps:\n\tgit-bisect start [<files>]\n\t\t- Reset to start bisecting.  If any files are specified,\n\t\t  only they will be checked out as bisection proceeds.\n\tgit-bisect good [<revision>]\n\t\t- Record the revision as \"good\".  The change being sought\n\t\t  must be after this revision.\n\tgit-bisect bad [<revision>]\n\t\t- Record the revision as \"bad\".  The change being sought\n\t\t  must be before or equal to this revision.\n\tAs soon as you have specified one good version and one bad version,\n\tgit-bisect will find a halfway point and check out that\n\trevision.  Build and test it, then report it as good or bad,\n\tand git-bisect will narrow the search.  Finally, git-bisect\n\twill tell you exactly which change caused the problem.\n\tgit-bisect log\n\t\t- Show a history of revisions.\n\tgit-bisect replay\n\t\t- Replay (part of) a git-bisect log.  Generally used\n\t\t  to recover from a mistake, you can truncate the log\n\t\t  before the mistake and replay it to continue.\n\tIf git-bisect chooses a version that cannot build, or you\n\tare otherwise unable to determine whether it is good or bad,\n\tyou can change revisions with \"git-reset --hard <revision>\"\n\tto another checkout between the current good and bad limits, and\n\tcontinue from there.  \"git-reset --hard <revision>\" is generally\n\tdangerous, but you are on a scratch branch.\n\n\tThis can, of course, be used to look for any change, even\n\tone for the better, if you can avoid being confused by the\n\tterms \"good\" and \"bad\".\ngit-branch.sh\n\tMost commonly used bare, to show the available branches.\n\tShow, create, or delete a branch.  The current branches\n\tare simply the contents of .git/refs/heads/.\n\tNote that this does NOT switch to the created branch!\n\tFor the common case of creating a branch and immediately\n\tswitching to it, \"git-checkout -b <branch>\" is simpler.\ngit-checkout.sh\n\tThis does two superficially similar but very different things\n\tdepending on whether any files or paths are specified on the\n\tcommand line.\n\n\tgit-checkout [-f] [-b <new-branch>] <branch>\n\t\tThis switches (changes the HEAD symlink to) the specified\n\t\tbranch, updating the index and working directory to\n\t\treflect the change.  This preserves changes in the\n\t\tworking directory unless -f is specified.\n\t\tIf -b is specified, a new branch is started from the\n\t\tspecified point and switched to.  If <branch> is omitted,\n\t\tit defaults to HEAD.  This is the usual way to start a\n\t\tnew branch.\n\n\tgit-checkout [<branch>] [--] <paths>...\n\t\tThis replaces the files specified by the given paths with\n\t\tthe versions from the index or the specified branch.\n\t\tIt does NOT affect the HEAD symlink, just replaces the\n\t\tspecified paths.  This form is like a selective form of\n\t\t\"git-reset\".  Normally, this can guess whether the first\n\t\targument is a branch name or a path, but you can use\n\t\t\"--\" to force the latter interpretation.\n\n\tWith no branch, this is used to revert a botched edit of a\n\tparticular file.\n\n\tBoth forms use git-read-tree internally, but the net effect is\n\tquite different.\ngit-commit.sh\n\tCommit changes to the revision history.  In terms of primitives,\n\tthis does three things:\n\t1) Updates the index file with the working directory files\n\t   specified on the command line, or -a for all (using\n\t   git-diff-files --name-only | git-update_index),\n\t2) Prompts for or generates a commit message, and then\n\t3) Creates a commit object with the current index contents.\n\n\tThe prompt for a commit message includes the output of git-status,\n\tso you can see what changes are being committed.\n\n\tThis also executes the pre-commit, commit-msg, and\n\tpost-commit hooks if present.\n\n\tFiles deleted from the working tree will be removed from the\n\tindex, but newly added files will not be automatically added,\n\teven if explicitly specified on the command line; you must use\n\tgit-add for that.\n\n\tNote that the default action, with no command line arguments,\n\tis to commit only what's already in the index.  The equivalent\n\tof \"cvs commit\" is \"git-commit -a\".\ngit-reset.sh\n\tExplained in detail in \"resetting\", above.  This modifies the\n\tcurrent branch head reference (as pointed to by .git/HEAD)\n\tto refer to the given commit.  It does not modify .git/HEAD \n\tReset the current HEAD to the specified commit, so that future\n\tcheckins will be relative to it.  There are three\n\tvariations:\n\t--soft: Just move the HEAD link.  The index is unchanged.\n\t--mixed (default): Move the HEAD link and update the index file.\n\t\tAny local changes will appear not checked in.\n\t--hard: Move the HEAD links, update the index file, and\n\t\tcheck out the index, overwriting the working\n\t\tdirectory.  Like \"cvs update -C\".\n\tIn case of accidents, this copies the previous head\n\tobject ID to ORIG_HEAD (which is NOT a symlink).\ngit-status.sh\n\tShow all the files in the working directory and index that have\n\tbeen changed since the current HEAD.  The basic categories are:\n\t1) Changed in the index, will be included in the next commit.\n\t2) Changed in the working directory but NOT in the index; will\n\t   be committed only if mentioned on the git-commit command line\n\t   (or added manually via git-update-index)\n\t3) Not tracked by git, but not explicitly ignored, either.\n\n\n+ Cherry-picking\n\tCherry-picking is the process of taking part of the changes\n\tintroduced on one tree and applying those changes to another.\n\tThis doesn't produce a parent/descendant relationship in the\n\tcommit history.\n\n\tTo produce that relationship, there's a special type of merge you\n\tcan do if you've taken everything you want off a branch and\n\twant to show it in the merge history without actually importing\n\tany changes from it: ours.  \"git-merge -s ours\" will generate a\n\tcommit that shows some branches were merged in, but not\n\tactually alter the current HEAD source code in any way.\n\n\tOne thing cherry-picking is sometimes used for is taking a\n\tdevelopment branch and re-organizing the changes into a patch\n\tseries for submission to the Linux kernel.\ngit-cherry.sh\n\tThis searches a branch for patches which have not been applied\n\tto another.  Basically, it finds the unpicked cherries.\n\tIt searches back to the common ancestor of the named branch and\n\tthe current head using git-patch-id to identify similarity\n\tin patches.\n  git-patch-id\n\tGenerate a hash of a patch, ignoring whitespace and line numbers\n\tso that \"the same\" patch, even relative to a different code base,\n\tprobably has the same hash, and different patches almost certainly\n\thave different ones.  git-cherry looks for patch hashes which\n\tare present on the branch (source branch) that are not present\n\ton the trunk (destination branch).\ngit-cherry-pick.sh\n\tGiven a commit (on a different branch), compute a diff between\n\tit and its immediate parent, and apply it to the current HEAD.\n\tThis is actually the same script as \"git revert\", but works\n\tforward.  git-cherry finds the patches, this merges them.\n\tHandles failures gracefully.\ngit-rebase.sh\n\tMove a branch to a more recent \"base\" release.\tThis just extracts\n\tall the patches applied on the local head since the last merge\n\twith upstream (using git-format-patch) and re-applies them\n\trelative to the current upstream with git-am (explained under\n\t\"accepting changes by e-mail\").  Finally, it deletes the old\n\tbranch and gives its name to the new one, so your branch now\n\tcontains all the same changes, but relative to a different base.\n\tBasically the same as cherry-picking an entire branch.\n\t(This uses git-cherry to find the patches, so is able to cope\n\twith patches that were applied to the base.)\ngit-revert.sh\n\tUndo a commit.\tBasically \"patch -R\" followed by a commit.\n\tThis is actually the same script as \"git-cherry-pick\", just\n\tapplies the patch in reverse, undoing a change that you don't\n\twish to back up to using git-reset.  Handles failures gracefully\n\tby telling the user what to do.\n\tThis reversion will create a commit in the history; it is\n\tnot like git-reset which erases history.\n\n+ Accepting changes by e-mail\ngit-apply\n\tApply a (git-style extended) patch to the current index\n\tand working directory.\ngit-am.sh\n\tThe new and improved \"apply an mbox\" script.  Takes an\n\tmbox-style concatenation of e-mails as input and batch-applies\n\tthem, generating one commit per message.  Can resume after\n\tstopping on a patch problem.\n\t(Invoke it as \"git-am --skip\" or \"git-am --resolved\" to\n\tdeal with the problematic patch and continue.)\n  git-mailinfo\n\tGiven a single mail message on stdin (in the Linux standard\n\tSubmittingPatches format), extract a commit message and\n\tthe patch proper.\n  git-mailsplit\n\tSplit an mbox into separate files.\n  git-applypatch.sh\n\tTries simple git-apply, then tries a few other clever merge\n\tstrategies to get a patch to apply.  Used in the main loop\n\tof git-am and git-applymbox.\ngit-applymbox.sh\n\tThis is Linus's original apply-mbox script.  Mostly superseded by\n\tgit-am (which is friendlier and has more features), but he still\n\tuses it, so it's maintained.  This is so old it was originally\n\ta test of the git core called \"dotest\", and that name is still\n\tlurking in the temp file names.\n\n+ Publishing changes by e-mail\ngit-format-patch.sh\n\tGenerate a series of patches, in the preferred Linux kernel\n\t(Documentation/SubmittingPatches) format, for posting to lkml\n\tor the like.  This formats every commit on a branch as a separate\n\tpatch.\ngit-send-email.perl\n\tActually e-mail the output of git-format-patch.\n\t(This uses direct SMTP, a matter of some controversy.  Others feel\n\tthat /bin/mail is the correct local mail-sending interface.)\n\n+ Merging\ngit-merge.sh\n\tMerge one or more \"remote\" heads into the current head.\n\tSome changes, when there has been change only on one branch or\n\tthe same change has been made to all branches, can be resolved\n\tby the \"trivial in-index\" merge done by git-read-tree.\tFor more\n\tcomplex cases, git provides a number of different merge strategies\n\t(with reasonable defaults).\n\n\tNote that merges are done on a filename basis.\tWhile git tries\n\tto detect renames when generating diffs, most merge strategies\n\tdon't track them by renaming.  (The \"recursive\" strategy, which\n\trecently became the default, is a notable exception.)\n  git-merge-base\n\tFinds a common ancestor to use when comparing the changes made\n\ton two branches.  The simple case is straightforward, but if\n\tthere have been cross-merges between the branches, it gets\n\tsomewhat hairy.  The algorithm is not 100% final yet.\n\t(There's also --all, which lists all candidates.)\n  git-merge-index\n\tThis is the outer merging loop.  It takes the name of a one-file\n\tmerge executable as an argument, and runs it for every incomplete\n\tmerge.\n    git-merge-one-file.sh\n\tThis is the standard git-merge-index helper, that tries to\n\tresolve a 3-way merge.  A helper used by all the merge strategies.\n\t(Except \"recursive\" which has its own equivalent.)\n  git-merge-octopus.sh\n\tMany-way merge.  Overlaps should be negligible.\n  git-merge-ours.sh\n\tA \"dummy\" merge strategy helper.  Claims that we did the merge, but\n\tactually takes the current tree unmodified.  This is used to\n\tcleanly terminate side branches that heve been cherry-picked in.\n  git-merge-recursive.py\n\tA somewhat fancier 3-way merge.   This handles multiple cross-merges\n\tbetter by using multiple common ancestors.\n  git-merge-resolve.sh\n  git-merge-stupid.sh\n\tNot actually used by git-merge, this is a simple example\n\tmerge strategy.\ngit-read-tree\n\tRead the given tree into the index.  This is the difference\n\tbetween the \"--soft\" and \"--mixed\" modes of git-reset, but the\n\timportant thing this command does is simple merging.\n\tIf -m is specified, this can take up to three trees as arguments.\ngit-resolve.sh\n\tOBSOLETE.  Perform a merge using the \"resolve\" strategy.\n\tHas been superseded by the \"-s resolve\" option to git-merge\n\tand git-pull.\ngit-octopus.sh\n\tOBSOLETE.   Perform a merge using the \"octopus\" strategy.\n\tHas been superseded by the \"-s octopus\" option to git-merge\n\tand git-pull.\n\n+ Making releases\ngit-get-tar-commit-id\n\tReads out the commit ID that git-tar-tree puts in its output.\n\t(Or fails if this isn't a git-generated tar file.)\ngit-tag.sh\n\tCreate a tag in the refs/tags directory.  There are two kinds:\n\t\"lightweight tags\" are just references to commits.  More\n\tserious tags are GPG-signed tag objects, and people receiving\n\tthe git tree can verify that it is the version that you released.\n  git-mktag\n\tCreates a tag object.  Verifies syntactic correctness of its\n\tinput.  (If you want to cheat, use git-hash-object.)\ngit-tar-tree\n\tGenerate a tar archive of the named tree.  Because git does NOT\n\ttrack file timestamps, this uses the timestamp of the commit,\n\tor the current time if you specify a tree.\n\tAlso stores the commit ID in an extended tar header.\ngit-verify-tag.sh\n\tGiven a tag object, GPG-verify the embedded signature.\n\n+ Accepting changes by network\n\tPulling consists of two steps: retrieving the remote commit\n\tobjects and everything they point to (including ancestors),\n\tthen merging that into the desired tree.  There are still\n\tseparate fetch and merge commands, but it's more commonly done\n\twith a single \"git-pull\" command.  git-fetch leaves the commit\n\tobjects, one per line, in .git/FETCH_HEAD.  git-merge will\n\tmerge those in if that file exists when it is run.\n\n\tReferences to remote repositories can be made with long URLs,\n\tor with files in the .git/remotes/ directory.  The latter\n\talso specifies the local branches to merge the fetched data into,\n\tmaking it very easy to track a remote repository.\ngit-clone.sh\n\tCreate a new local clone of a remote repository.\n\t(Can do a couple of space-sharing hacks when \"remote\" is on\n\ta local machine.)\n\n\tYou only do this once.\n  git-clone-pack\n\tRuns git-upload-pack remotely and places the resultant pack\n\tinto the local repository.  Supports a variety of network\n\tprotocols, but \"remote\" can also be a different directory on\n\tthe current machine.\ngit-fetch.sh\n\tFetch the named refs and all linked objects from a remote repository.\n\tThe resultant refs (tags and commits) are stored in .git/FETCH_HEAD,\n\twhich is used by a later git-resolve or git octopus.\n\n\tThis is the first half of a \"git pull\" operation.\n  git-fetch-pack\n\tRetrieve missing objects from a remote repository.\n  git-local-fetch\n\tDuplicates a git repository from the local system.\n\t(Er... is this used anywhere???)\n  git-http-fetch\n\tDo a fetch via http.  Http requires some kludgery on the\n\tserver (see git-update-server-info), but it works.\n  git-ssh-fetch\n\tDo a fetch via ssh.\ngit-ls-remote.sh\n\tShow the contents of the refs/heads/ and/or refs/tags/ directories\n\tof a remote repository.  Useful to see what's available.\n  git-peek-remote\n\tHelper C program for the git-ls-remote script.  Implements the\n\tgit protocol form of it.\ngit-parse-remote.sh\n\tHelper script to parse a .git/remotes/ file.  Used by a number\n\tof these programs.\ngit-pull.sh\n\tFetches specific commits from the given remote repository,\n\tand merges everything into the current branch.\tIf a remote\n\tcommit is named as src:dst, this merges the remote head \"src\"\n\tinto the branch \"dst\" as well as the trunk.  Typically, the \"dst\"\n\tbranch is not modified locally, but is kept as a pristine copy\n\tof the remote branch.\n\n\tOne very standard example of this contention is that\n\ta repository that is tracking another specifies \"master:origin\"\n\tto provide a pristine local copy of the remote \"master\"\n\tbranch in the local branch named \"origin\".\n  git-ssh-pull\n\tA helper program that pulls over ssh.\ngit-shell\n\tA shell that can be used for git-only users.  Allows git\n\tpush (git-receive-pack) and pull (git-upload-pack) only.\n  git-receive-pack\n\tReceive a pack from git-send-pack, validate it, and add it to\n\tthe repository.  Adding just the bare objects has no security\n\timplications, but this can also update branches and tags, which\n\tdoes have an effect.\n\tRuns pre-update and post-update hooks; the former may do\n\tpermissions checking and disallow the upload.\n\tThis is the command run remotely via ssh by git-push.\n\n+ Publishing changes by network\ngit-daemon\n\tA daemon that serves up the git native protocol so anonymous\n\tclients can fetch data.  For it to allow export of a directory,\n\tthe magic file name \"git-daemon-export-ok\" must exist in it.\n\n\tThis does not accept (receive) data under any circumstances.\ngit-push.sh\n\tGit-pull, only backwards.  Send local changes to a remote\n\trepository.  The same .git/remotes/ short-cuts can be used,\n\tand the same src:dst syntax.  (But this time, the src is local\n\tand the dst is remote.)\n  git-http-push\n\tA helper to git-push to implement the http: protocol.\n  git-ssh-push\n\tA helper to git-push to push over ssh.\n  git-ssh-upload\n\tAnother helper.  This just does the equivalent of \"fetch\"\n\t(\"throw\"?) and doesn't actually merge the result.  Obsolete?\ngit-request-pull.sh\n\tGenerate an e-mail summarizing the changes between two commits,\n\tand request that the recipient pull them from your repository.\n\tJust a little helper to generate a consistent and informative\n\tformat.\ngit-send-pack\n\tPack together a pile of objects missing at the destination and\n\tsend them.  This is the sending half that talks to a remote\n\tgit-receive-pack.\ngit-update-server-info\n\tTo run git over http, auxiliary info files are required that\n\tdescribes what objects are in the repository (since git-upload-pack\n\tcan't generate this on the fly).  If you want to publish a\n\trepository via http, run this after every commit.  (Typically\n\tvia the hooks/post-update script.)\ngit-upload-pack\n\tLike git-send-pack, but this is invoked by a remote git-fetch-pack.\n"},{"id":"13410","messageId":"20051209094328.GT22159@pasky.or.cz","threadId":"2789","inReplyTo":"20051209054304.3908.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-12-09T09:43:28Z","receivedAt":"2005-12-09T09:43:28Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"  BTW, such a \"wide\" reply is a bit hard to handle - it might be perhaps\nmore practical to make separate replies at least to the mails whose\ncontents does not overlap. Also, people would not get Cc's of subthreads\nthey are not involved with.\n\nDear diary, on Fri, Dec 09, 2005 at 06:43:04AM CET, I got a letter\nwhere linux@horizon.com said that...\n> Finally, pasky@suse.de wrote:\n> > That said, the \"git for the confused\" contains a lot of nice points, but\n> > I don't think it's a good approach to just have extra document for\n> > clarifying this stuff. It would be much better if the stock\n> > documentation itself would not be confusing in the first place. Same\n> > goes for the \"commands overview\" (BOUND to get out-of-date over time\n> > since it's detached from the normal per-command documentation; we have\n> > troubles huge enough to keep usage strings in sync, let alone the\n> > manpages).\n> \n> I don't think it's the ideal solution either, but the idea of trying to\n> supplant Linus' tutorial is a bit alarming given my current still-novice\n> state.  I've been dabbling with git for a few weeks; many of the people\n> on this list have been using git in earnest for most of its life.\n\nNow that's precisely what's most precious on you :-) - you have a fresh\nperspective (and you don't seem to appear as a bad writer, at least to\nme), actually much more important that technical correctness especially\nfor non-reference documentation like this; we'll catch possible\ninaccuracies while reviewing, that's the least thing.\n\n> Unfortunately, given the number of commands, you can't just document\n> them well individually.  Some overview of how they fit together into\n> a system is required.\n\nHmm. Well, actually... what's the point? If I want to get a really quick\noverview, I do\n\n\twhatis git\n\nand it will DTRT. But when do I need something more detailed but not yet\nthe manual page of the given command?\n\nNow, having a task-based structured documentation (also called \"user\nmanual\" ;-) is an entirely different story and yes, that would be\nextremely useful.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nVI has two modes: the one in which it beeps and the one in which\nit doesn't.\n"},{"id":"13414","messageId":"20051209140123.3234.qmail@science.horizon.com","threadId":"2789","inReplyTo":"20051209094328.GT22159@pasky.or.cz","subject":"Re: as promised, docs: git for the confused","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2005-12-09T14:01:23Z","receivedAt":"2005-12-09T14:01:23Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":">   BTW, such a \"wide\" reply is a bit hard to handle - it might be perhaps\n> more practical to make separate replies at least to the mails whose\n> contents does not overlap. Also, people would not get Cc's of subthreads\n> they are not involved with.\n\nSorry... it was one edit session while I made all the corrections,\nand it was just more natural...\n\n>> Unfortunately, given the number of commands, you can't just document\n>> them well individually.  Some overview of how they fit together into\n>> a system is required.\n\n> Hmm. Well, actually... what's the point? If I want to get a really quick\n> overview, I do\n>\n>\twhatis git\n>\n> and it will DTRT. But when do I need something more detailed but not yet\n> the manual page of the given command?\n\n\"I want to do X and Y but not Z.  What commands are worth knowing?\"\n\nI have 106 git-* commands available to me (my document covers 105;\nI'll have to find the extra), and the biggest question I have is\n\"how many of those man pages can I get away with NOT reading?\"\n\nHeck, that categorized list is what I started out writing, and I happen\nto think it's the most important part of the whole document.\n\nThe man page tells me HOW to execute a command.  But before I'm ready for\nthat level of detail, I need to figure out WHICH command to execute.\nTo be specific, I need to know the terrain just well enough so I can\nplan a route from where I am to where I want to be.  Then I can look\ninto the details of each step.\n\nBut without that overview, my trip is going to take me into a lot of dead\nends, because I'm executing commands that I think are getting me closer,\nbut I have the wrong mental model of what \"close\" is.\n\nOr perhaps I found one command that sort-of does what I want an\nmissed the one that works better.\n\n\n(BTW, don't you mean \"whatis -w git\\*\"?)\n"},{"id":"13418","messageId":"Pine.LNX.4.58.0512090846480.23358@shark.he.net","threadId":"2789","inReplyTo":"20051209140123.3234.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Randy.Dunlap","fromEmail":"rdunlap@xenotime.net","sentAt":"2005-12-09T16:49:39Z","receivedAt":"2005-12-09T16:49:39Z","isPatch":false,"sender":{"key":"rdunlap@xenotime.net","avatar":null},"body":"On Fri, 9 Dec 2005 linux@horizon.com wrote:\n\n> >> Unfortunately, given the number of commands, you can't just document\n> >> them well individually.  Some overview of how they fit together into\n> >> a system is required.\n>\n> > Hmm. Well, actually... what's the point? If I want to get a really quick\n> > overview, I do\n> >\n> >\twhatis git\n> >\n> > and it will DTRT. But when do I need something more detailed but not yet\n> > the manual page of the given command?\n>\n> \"I want to do X and Y but not Z.  What commands are worth knowing?\"\n\nI agree big time.  Even for quilt (about 30 commands),\nI wrote a summary (cheat sheet) of usage models:\n\na.  making a new patch:  use this series of commands\nb.  importing patches:  use this other series of commands\nc.  other patch management commands\n\n\n> I have 106 git-* commands available to me (my document covers 105;\n> I'll have to find the extra), and the biggest question I have is\n> \"how many of those man pages can I get away with NOT reading?\"\n>\n> Heck, that categorized list is what I started out writing, and I happen\n> to think it's the most important part of the whole document.\n>\n> The man page tells me HOW to execute a command.  But before I'm ready for\n> that level of detail, I need to figure out WHICH command to execute.\n> To be specific, I need to know the terrain just well enough so I can\n> plan a route from where I am to where I want to be.  Then I can look\n> into the details of each step.\n>\n> But without that overview, my trip is going to take me into a lot of dead\n> ends, because I'm executing commands that I think are getting me closer,\n> but I have the wrong mental model of what \"close\" is.\n\n-- \n~Randy\n"},{"id":"13421","messageId":"7vzmna2ig2.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"20051209140123.3234.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-09T19:12:29Z","receivedAt":"2005-12-09T19:12:29Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"linux@horizon.com writes:\n\n> \"I want to do X and Y but not Z.  What commands are worth knowing?\"\n>\n> I have 106 git-* commands available to me (my document covers 105;\n> I'll have to find the extra), and the biggest question I have is\n> \"how many of those man pages can I get away with NOT reading?\"\n\nThis primarily comes from the way git is architected.  We have\nmany commands that are not so interesting from the end-user\nperspective.  If git were architected differently, many of them\nmay not exist in executable command form, but would instead be\nlibrary functions and listed in section 3git of the manual.\n\n> Heck, that categorized list is what I started out writing, and I happen\n> to think it's the most important part of the whole document.\n\nAnd I think I agree it but with a twist.  The full listing for\nPorcelain writers is mostly fine as is in git(7); maybe what you\nwrote have clarification material, in which case I'd appreciate\na patch to Documentation/git.txt.\n\nWhat we need is a separate list aimed for end users, and\nsomebody looking only at that list should be able to do\nday-to-day work with only the commands listed there, and does\nnot even have to know something called rev-parse or merge-base\nexist.\n\nA good start for this list would be the list of selected\ncommands git.sh used to show (these days, git.c wrapper shows\neverything that starts with \"git\", but the old one limited\nitself to show only the ones that may be useful by the\nend-user).\n\n> The man page tells me HOW to execute a command.  But before I'm ready for\n> that level of detail, I need to figure out WHICH command to execute.\n\nExactly.  The tutorial can also use a minor split.  It starts\nout to give taste of internal workins of Porcelains, but ends up\nbeing a fuzzy mix of \"user manual\" and \"hints to porcelain\nwriters\".  We probably should have a separate \"end user\ntutorial\" --- the Alice-Bob scenario by Horst might be a good\nplace to start.\n"},{"id":"13425","messageId":"20051209213335.GU22159@pasky.or.cz","threadId":"2789","inReplyTo":"20051209140123.3234.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-12-09T21:33:35Z","receivedAt":"2005-12-09T21:33:35Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Dec 09, 2005 at 03:01:23PM CET, I got a letter\nwhere linux@horizon.com said that...\n> >> Unfortunately, given the number of commands, you can't just document\n> >> them well individually.  Some overview of how they fit together into\n> >> a system is required.\n> \n> > Hmm. Well, actually... what's the point? If I want to get a really quick\n> > overview, I do\n> >\n> >\twhatis git\n> >\n> > and it will DTRT. But when do I need something more detailed but not yet\n> > the manual page of the given command?\n> \n> \"I want to do X and Y but not Z.  What commands are worth knowing?\"\n\nWell, yes, that's the approach I advocate as well! It's precisely the\n\"task-based structured documentation\" I talked about.\n\nBut the command listing is something different, actually the opposite:\n\n\"See, you have all those commands A, B, C. And this is what you can do\nwith them.\"\n\nThat's to say, the former requires a lot more effort and writing than\nthe latter and the latter has its uses as well, although I still think\nthe former is superior. :-)\n\n> (BTW, don't you mean \"whatis -w git\\*\"?)\n\n$ whatis git\ngit                  (7)  - the stupid content tracker\ngit-add              (1)  - Add files to the index file\ngit-am               (1)  - Apply a series of patches in a mailbox\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nVI has two modes: the one in which it beeps and the one in which\nit doesn't.\n"},{"id":"13426","messageId":"20051209215414.14072.qmail@science.horizon.com","threadId":"2789","inReplyTo":"7vzmna2ig2.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2005-12-09T21:54:14Z","receivedAt":"2005-12-09T21:54:14Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"> This primarily comes from the way git is architected.  We have\n> many commands that are not so interesting from the end-user\n> perspective.  If git were architected differently, many of them\n> may not exist in executable command form, but would instead be\n> library functions and listed in section 3git of the manual.\n\nBut you also have commands of interest or not to different classes\nof users.\n\nSome users want to track someone else's repository.\nOthers want to generate their repository from scratch.\nOr maybe import some history from CVS.\n\nSome users spend all day applying patches.\nSome spend all day creating patches.\nSome just want to retrieve the kernel and run \"git bisect\"\nto help the kernel developers.  They will neither generate\nnor apply patches.\nSome want access to a developer's git repository to test\nbleeding-edge drivers.\n\nSome folks want to set up remote access to a shared repository\nwithin a development group.\nSome folks want to set up an anonymous git server.\n\nEt cetera.  There are many different constituencies, who will\nwant access to a different subset of the commands.\n\n> Exactly.  The tutorial can also use a minor split.  It starts\n> out to give taste of internal workins of Porcelains, but ends up\n> being a fuzzy mix of \"user manual\" and \"hints to porcelain\n> writers\".  We probably should have a separate \"end user\n> tutorial\" --- the Alice-Bob scenario by Horst might be a good\n> place to start.\n\nThat much, I definitely agree with.  Mixing the two is confusing.\n"},{"id":"13427","messageId":"7vmzj9zwfu.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"20051209215414.14072.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-09T23:23:49Z","receivedAt":"2005-12-09T23:23:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"linux@horizon.com writes:\n\n> Some users want to track someone else's repository.\n> Others...\n\nExactly.  That's why task oriented list would be most useful.\nHere is a starter.\n\n\nEveryday GIT Cheat Sheet Or Git With 20 Commands\n================================================\n\nRepository Administration\n-------------------------\n\n  * \"init-db\" or \"clone\" to create the initial repository.\n  * hooks.\n    - public accessible via dumb protocols: need\n      update-server-info in hooks/post-update\n    - CVS style shared repository: see howto/update-hook-example\n      for ideas on branch head policy\n  * \"fsck-objects\", \"repack\" and \"prune\".\n\n\nIndividual Developer\n--------------------\n\nStandalone tasks\n\n  * \"show-branch\" or \"gitk\" to see where you are.\n  * \"diff\" or \"status\" to see what you are in the middle of.\n  * \"log\" to see what happened.\n  * \"whatchanged\" to find out where things come from.\n  * \"checkout\" and \"checkout -b\" to switch branches.\n  * \"commit\" to advance the current branch head.\n  * \"reset\" to undo unpublished changes.\n  * \"checkout -- path\" to undo working tree chanegs.\n  * \"pull .\" to merge between branches.\n  * \"rebase\" to maintain topic branches.\n  * \"fsck-objects\", \"repack\" and \"prune\".\n\nWorking as a participant\n\n  * all the commands useful for standalone individual developer tasks.\n  * \"pull origin\" to keep up-to-date.\n  * \"push upstream\" in CVS style shared repository workflow.\n  * \"format-patch\" in kernel style public forum workflow.\n\nIntegrator\n----------\n\n  * all the commands useful for standalone individual developer tasks.\n  * \"am\" to apply patches.\n  * \"pull somewhere-else\" to merge from trusted lieutenants.\n  * \"format-patch\" to send suggested alternative to contributors.\n  * \"revert\" to undo botched changes.\n  * \"push public\" to publish the results.\n\n\nIt might be surprising that only handful commands are of\neveryday use among 100+, but the ones listed above are the only\nones I use every day.  The exact number depends on how you count\nmulti-purpose commands like \"checkout\" and \"pull\", but only\nthese need to be learned to play all roles listed above.\n\n\tam\n\tcheckout\n\tcheckout -- path\n\tcheckout -b\n\tcommit\n\tdiff\n\tfetch\n\tformat-patch\n\tfsck-objects\n\tgitk\n\tinit-db\n\tlog\n\tprune\n\tpull .\n\tpull other\n\tpush\n\trebase\n\trepack\n\treset\n\trevert\n\tshow-branch\n\tstatus\n\twhatchanged\n"},{"id":"13428","messageId":"7vk6edycea.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"20051209054401.4016.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-10T01:22:05Z","receivedAt":"2005-12-10T01:22:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"linux@horizon.com writes:\n\n> ....  There has\n> been motion towards putting the git-* commands in their own directory,\n> to be invoked by the /usr/bin/git wrapper.\n>\n> In this case, you'll have to leave out the initial hyphen, or add the\n> git binary directory to your $PATH.\n\nMisleading, if not incorrect.  git wrapper and a handful others\nsuch as receive-pack and upload-pack that need to be directly\ninvoked via ssh will remain in /usr/bin and the users do not\nneed to worry about where the rest went.  The recommended way\nwould be to use non-dash form.  If you care about the extra\nindirection done by \"git\" in your script, run \"git --exec-path\"\nonce to get the git binary directory and prepend the result to\nPATH.  You _could_ do the latter for your interactive shell\nsession as well, but it is not actively recommended.\n\n> * Resetting\n>\n> There are actually three kinds of git-reset:\n> git-reset --soft: Only overwrite the reference.  If you need to, you\n> \tcan put everything back with a second git-reset --soft OLD_HEAD.\n\nI am not sure what you mean by \"second\" here.  Did you mean to\nsay something like this?\n\n    After you did \"git-reset --soft somewhereyoudidnotmeantogo\"\n    by mistake, you can recover with \"git-reset --soft ORIG_HEAD\".\n\n> There is an undelete: git-reset stores the previous HEAD commit in\n> OLD_HEAD.\n\nAnd probably you meant to say ORIG_HEAD (the latter part of the\ndocumentation you do say ORIG_HEAD).\n\nNow I finally had a chance to finish the command list part.\n\n> git-prune.sh\n>...\n> \teliminate the \n\nIncomplete sentence.\n\n> git-pack-objects\n> \tGiven a list of objects on stdin, build a pack file.  This is\n> \ta helper used by the various network communication scripts.\n\n... and by (obviously) git-repack.\n\n> + Accepting changes by e-mail\n> git-apply\n> \tApply a (git-style extended) patch to the current index\n> \tand working directory.\n\nActually it can take \"patch -p1\" format patch, and the input\ndoes not have to be git-extended patch.  Two extra things you\ncan do when the input is git-extended patch is to apply\nrename/copy and filemode changes.\n\n>   git-merge-base\n>...\n> \tsomewhat hairy.  The algorithm is not 100% final yet.\n\nI do not think there is any remaining issues with the current\nalgorithm, so you can mark it final now.\n\n>   git-mktag\n> \tCreates a tag object.  Verifies syntactic correctness of its\n> \tinput.  (If you want to cheat, use git-hash-object.)\n\nIs there a particular reason to encourage cheating?  IOW, is\nmktag cumbersome to use, and if so how?\n\n>   git-local-fetch\n> \tDuplicates a git repository from the local system.\n> \t(Er... is this used anywhere???)\n\nNot by git barebone Porcelain, but other Porcelains can use it\nif they want.  Same thing for git-ssh-fetch.\n\n>   git-ssh-pull\n> \tA helper program that pulls over ssh.\n\ngit-ssh-pull and git-ssh-fetch are the same program, and the\nformer is only for backward compatibility.  Earlier, only\ngit-ssh-pull/git-ssh-push pair existed and they continue to\ninvoke the other on the other end.  Terminology standardized to\ncall downloading phase \"-fetch\", and its counterpart \"-upload\";\nso git-ssh-fetch invokes git-ssh-upload on the other end (so\nssh-pull/ssh-push can be viewed obsolete if you want).\n"},{"id":"13432","messageId":"7v7jadwfdj.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"20051209054401.4016.qmail@science.horizon.com","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-10T08:00:40Z","receivedAt":"2005-12-10T08:00:40Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"linux@horizon.com writes:\n\n> Like other version control systems, git has a current version (referred\n> to as HEAD) in its object database, you make changes in the working\n> directory, and then commit them, which appends a new version and makes\n> that the new HEAD.\n>\n> However, there's also this \"index\" thing interposed.  As \"man git\"\n> explains, you can have one version of the file in the HEAD, a second\n> in the index, and a third in the working directory.  That's weird\n> and confusing - why does git allow that?  Why isn't the index just an\n> implementation detail that caches the HEAD until you commit a new one?\n>\n> The answer is merging, which does all its work in the index.  Being a\n> toolkit, git has to pass partial merges around between its various\n> tools, which means keeping track of multiple files all competing for\n> the same name.  Neither the object database nor the working directory\n> let you have multiple files with the same name.\n\nI do not necessarily agree with this claim that merging is the\nwhole story about index.  As the steps in the hello/example\ntutorial demonstrate, index is used to build up what you will\ncommit incrementally, and you can use this facility to view your\nchanges incrementally.\n\nYour workflow could be like this:\n\n    $ git checkout\n    $ hack away\n    $ git diff ;# what have I done so far?\n    $ git diff HEAD ;# this one shows the same as the above.\n\n    $ git update-index frotz ;# now I am satisfied with my progress so far.\n    $ hack away further\n    $ git diff ;# what have I done since my last \"satisfactory checkpoint\"?\n    $ git diff HEAD ;# changes since the last commit -- this is\n    \t\t     # different from the above, and gives a lot\n\t\t     # more output\n    $ git update-index nitfol ;# I am happy with what I've done\n                               # to this file as well.\n    $ hack away further\n    $ git diff\t    ;# changes since the checkpoint\n    $ git update-index frotz nitfol\n    $ git diff HEAD ;# final pre-commit review\n    $ git commit\n\nYou could view updating the index as \"checking in\" and making a\ncommit as \"casting your cumulative check-ins in stone\".  You can\nmake \"check in\" as many times as you want, and there is \"git\nreset --mixed\" to uncheckin the index changes.  And by doing\nintermediate \"checkins\" to index file, you can limit what \"git\ndiff\" shows only to changes since your last checkpoint, as\nopposed to all the changes you have made since your last commit.\n\nThis is sometimes very useful, and I suspect your comment about\n\"commit -a will take care of everything, so you do not need to\nknow about update-index\" is coming from your ignoring this\naspect of update-index.\n"},{"id":"13433","messageId":"20051210105609.9994.qmail@science.horizon.com","threadId":"2789","inReplyTo":"7v7jadwfdj.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2005-12-10T10:56:09Z","receivedAt":"2005-12-10T10:56:09Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"> I do not necessarily agree with this claim that merging is the\n> whole story about index.  As the steps in the hello/example\n> tutorial demonstrate, index is used to build up what you will\n> commit incrementally, and you can use this facility to view your\n> changes incrementally.\n> \n> Your workflow could be like this:\n\n(Good example)\n\n> This is sometimes very useful, and I suspect your comment about\n> \"commit -a will take care of everything, so you do not need to\n> know about update-index\" is coming from your ignoring this\n> aspect of update-index.\n\nWell, yes and no.  I'm quite aware that the index can be used that way,\nbut I'm less certain it's a good idea.\n\nI have often wished for a very lightweight \"snapshot\" feature that I could\n(say) put in a Makefile at the end of every successful compile.  I don't\nwant to share those snapshots with the world, and I'll delete them next\n\"real\" commit, but they'll help me recover if I fumble-finger something.\n\nThink of it as an undo feature.  (With, of course, additional features\nlike the ability to see diffs between various stages.)\n\nYou can use the index as a one-level undo feature in a similar way.\nOr maybe, since it's manual, its like hitting save from an editor.\nEither way, the fact that it's only one level means that I have to\nthink about what I'm throwing away when I use it, which is somewhat\nannoying.\n\n\nAdd that to the fact that it's unlike other version control systems\n(including cogito) which go straight from the working directory into\nthe history, and I thought it better do downplay it.\n\nCertainly I think that people will *usually* just \"git-commit -a\" to\ncommit their current version.  Edit, compile, test, commit.  Except in\nunusual cases, I want the commit to reflect what I just tested.\n\nUsing git-update-index in the meantime is an optional extra.\n"},{"id":"13512","messageId":"Pine.LNX.4.64.0512120827440.15597@g5.osdl.org","threadId":"2789","inReplyTo":"7vmzj9zwfu.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-12-12T16:34:12Z","receivedAt":"2005-12-12T16:34:12Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 9 Dec 2005, Junio C Hamano wrote:\n>\n> Exactly.  That's why task oriented list would be most useful.\n> Here is a starter.\n> \n> \n> Everyday GIT Cheat Sheet Or Git With 20 Commands\n> ================================================\n\nWould this file perhaps also have examples?\n\nI really think a lot of people learn better from examples than from having \npointers to git programs that can be useful.\n\nFor example, earlier today I got the bash tar-ball because I had forgotten \nwhat the magic config option was to make bash do the right thing wrt pipe \nwrite errors. And because I'm totally dependent on \"git grep\" these days, \nI turned that tar-ball into a git archive. It's really a sinfully simple \nthing to do, but I don't think we mention that anywhere in the docs.\n\nHere's what I did:\n\n\t# Extract the thing as normal\n\tzcat < bash-3.0.tar.gz | tar xvf -\n\tcd bash-3.0/\n\n\t# make a git archive out of it\n\tgit init-db\n\tgit add .\n\tgit commit\n\nand that's it. That creates a git archive from a tar-ball. Very simple, \nand short sequences like these would make tons of sense for a \"cheat \nsheet\" like yours, and I really think most people can look at those three \ngit commands and suddenly they understand what they do a lot better than \nby reading the man-pages.\n\nOr maybe it's just me. But I know _I_ understand things better by seeing \nthe \"context\" that they are used in. Then I go to man-pages later on, if I \nwant to know the details.\n\nNo?\n\n\t\tLinus\n"},{"id":"13519","messageId":"20051212195319.11d41269.tihirvon@gmail.com","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512120827440.15597@g5.osdl.org","subject":"Re: as promised, docs: git for the confused","fromName":"Timo Hirvonen","fromEmail":"tihirvon@gmail.com","sentAt":"2005-12-12T17:53:19Z","receivedAt":"2005-12-12T17:53:19Z","isPatch":false,"sender":{"key":"tihirvon@gmail.com","avatar":null},"body":"On Mon, 12 Dec 2005 08:34:12 -0800 (PST)\nLinus Torvalds <torvalds@osdl.org> wrote:\n\n> Or maybe it's just me. But I know _I_ understand things better by seeing \n> the \"context\" that they are used in. Then I go to man-pages later on, if I \n> want to know the details.\n\nMe too.  BTW, new users very likely read tutorial.txt first.  But it is\nway too low level (git-cat-file, git-write-tree...).  Maybe those low\nlevel commands should be described in technical/ instead?  The tutorial\nwould be logical place for examples.\n\n-- \nhttp://onion.dynserv.net/~timo/\n"},{"id":"13520","messageId":"7v64pujj54.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512120827440.15597@g5.osdl.org","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-12T17:54:31Z","receivedAt":"2005-12-12T17:54:31Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> ... But I know _I_ understand things better by seeing \n> the \"context\" that they are used in. Then I go to man-pages later on, if I \n> want to know the details.\n>\n> No?\n\nAbsolutely.  It's the way how I pick up new things for me too.\n"},{"id":"13521","messageId":"Pine.LNX.4.64.0512121010550.15597@g5.osdl.org","threadId":"2789","inReplyTo":"20051212195319.11d41269.tihirvon@gmail.com","subject":"Re: as promised, docs: git for the confused","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-12-12T18:18:37Z","receivedAt":"2005-12-12T18:18:37Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 12 Dec 2005, Timo Hirvonen wrote:\n> \n> Me too.  BTW, new users very likely read tutorial.txt first.  But it is\n> way too low level (git-cat-file, git-write-tree...).  Maybe those low\n> level commands should be described in technical/ instead?  The tutorial\n> would be logical place for examples.\n\nI'd almost suggest skipping the technical notes in the current tutorial, \nand just gearing it directly more towards a regular user. \n\nWhen I started writing it, I cared more about people understanding how git \nworks internally. I think that was useful too, but I suspect that it's \nless useful than just knowing how to use git, and there _are_ enough \npeople out there that understand how git works under the hood that it \nprobably would be much better to concentrate on getting people _first_ \nused to using git, and then having a separate tutorial for \"what goes \nunder the hood\".\n\nSo instead of teaching people about \"git-read-tree --reset HEAD\" etc that \nyou'd never know on your own, just teach about \"git reset\". And not \nbothering with the \"git-write-tree + git-commit-tree + git-update-ref\" \napproach, just make people use \"git commit\" from the very beginning.\n\nAnybody willing to just strip out the raw internals talk?\n\nThen we could add a small section about importing from a tar-file. \n\n\t\t\tLinus\n"},{"id":"13527","messageId":"86y82qyrqs.fsf@blue.stonehenge.com","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512121010550.15597@g5.osdl.org","subject":"Re: as promised, docs: git for the confused","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-12-12T20:39:39Z","receivedAt":"2005-12-12T20:39:39Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Linus\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLinus> So instead of teaching people about \"git-read-tree --reset HEAD\" etc that \nLinus> you'd never know on your own, just teach about \"git reset\". And not \nLinus> bothering with the \"git-write-tree + git-commit-tree + git-update-ref\" \nLinus> approach, just make people use \"git commit\" from the very beginning.\n\nI learned more by reading the cg-tutorial, at least from the user\nperspective.  I then went back to the git-tutorial, and was able to\nfinally understand that these commands are worth ignoring. :)\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"13538","messageId":"7vek4hg824.fsf_-_@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512120827440.15597@g5.osdl.org","subject":"[PATCH] Everyday: some examples.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-13T00:22:11Z","receivedAt":"2005-12-13T00:22:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Fri, 9 Dec 2005, Junio C Hamano wrote:\n>>\n>> Exactly.  That's why task oriented list would be most useful.\n>> Here is a starter.\n>> \n>> \n>> Everyday GIT Cheat Sheet Or Git With 20 Commands\n>> ================================================\n>\n> Would this file perhaps also have examples?\n\nHow about...\n\n---\n\n Documentation/everyday.txt |   72 ++++++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 68 insertions(+), 4 deletions(-)\n\n44db136cad84c003506e231a38935ca6acba4d7d\ndiff --git a/Documentation/everyday.txt b/Documentation/everyday.txt\nindex 5775cd2..ded4d51 100644\n--- a/Documentation/everyday.txt\n+++ b/Documentation/everyday.txt\n@@ -59,9 +59,6 @@ following commands.\n \n   * gitlink:git-show-branch[1] to see where you are.\n \n-  * gitlink:git-diff[1] and gitlink:git-status[1] to see what\n-    you are in the middle of doing.\n-\n   * gitlink:git-log[1] to see what happened.\n \n   * gitlink:git-whatchanged[1] to find out where things have\n@@ -70,7 +67,11 @@ following commands.\n   * gitlink:git-checkout[1] and gitlink:git-branch[1] to switch\n     branches.\n \n-  * gitlink:git-update-index[1] to manage the index file.\n+  * gitlink:git-add[1] and gitlink:git-update-index[1] to manage\n+    the index file.\n+\n+  * gitlink:git-diff[1] and gitlink:git-status[1] to see what\n+    you are in the middle of doing.\n \n   * gitlink:git-commit[1] to advance the current branch.\n \n@@ -83,6 +84,37 @@ following commands.\n   * gitlink:git-rebase[1] to maintain topic branches.\n \n \n+Examples\n+~~~~~~~~\n+\n+* Extract a tarball and create a working tree and a new repository to keep track of it.\n+------------\n+$ tar zxf frotz.tar.gz\n+$ cd frotz\n+$ git-init-db\n+$ git add .\n+$ git commit -m 'import of frotz source tree.'\n+------------\n+\n+* Create a topic branch and develop\n+------------\n+$ git checkout -b private\n+$ edit/compile/test\n+$ git diff <1>\n+$ git checkout -- foo.c <2>\n+$ edit/compile/test\n+$ git commit -a -s <3>\n+$ git checkout master <4>\n+$ git pull . private <5>\n+\n+<1> to see what changes you are committing.\n+<2> revert your botched changes in selected path \"foo.c\".\n+<3> commit everything as you have tested.\n+<4> switch to the master branch.\n+<5> merge a topic branch into your master branch\n+------------\n+\n+\n Individual Developer (Participant)[[Individual Developer (Participant)]]\n ------------------------------------------------------------------------\n \n@@ -100,6 +132,38 @@ addition to the ones needed by a standal\n     you adopt Linux kernel-style public forum workflow.\n \n \n+Examples\n+~~~~~~~~\n+\n+* Clone the upstream and work on it.  Feed changes to upstream.\n+------------\n+$ git clone git://git.kernel.org/pub/scm/.../torvalds/linux-2.6 my2.6\n+$ cd my2.6\n+$ edit/compile/test; git commit -a -s <1>\n+$ git format-patch master <2>\n+$ git pull <3>\n+$ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL <4>\n+\n+<1> repeat as needed.\n+<2> extract patches from your branch for e-mail submission.\n+<3> \"pull\" fetches from \"origin\" by default and merges.\n+<4> fetch from a specific branch from a specific repository and and merge. \n+------------\n+\n+* Branch off of a specific tag.\n+------------\n+$ git checkout -b private2.6.14 v2.6.14 <1>\n+$ edit/compile/test; git commit -a\n+$ git checkout master\n+$ git format-patch -k -m --stdout v2.6.14..private2.6.14 |\n+  git am -3 -k <2>\n+<1> create a private branch based on a well known (but somewhat behind)\n+tag.\n+<2> forward port all changes in private2.6.14 branch to master\n+branch without formal \"merging\".\n+------------\n+\n+\n Integrator[[Integrator]]\n ------------------------\n \n-- \n0.99.9.GIT\n"},{"id":"13556","messageId":"20051213035842.GF10371@always.joy.eth.net","threadId":"2789","inReplyTo":"86y82qyrqs.fsf@blue.stonehenge.com","subject":"Re: as promised, docs: git for the confused","fromName":"Joshua N Pritikin","fromEmail":"jpritikin@pobox.com","sentAt":"2005-12-13T03:58:42Z","receivedAt":"2005-12-13T03:58:42Z","isPatch":false,"sender":{"key":"jpritikin@pobox.com","avatar":"https://gravatar.com/avatar/3f2561fdd7efac4e127dc65ac7e06f044069c115dcc94d0ac540f4126d47759d?d=mp&s=160"},"body":"On Mon, Dec 12, 2005 at 12:39:39PM -0800, Randal L. Schwartz wrote:\n> I learned more by reading the cg-tutorial, at least from the user\n> perspective.  I then went back to the git-tutorial, and was able to\n> finally understand that these commands are worth ignoring. :)\n\nI don't remmeber which documentation I read but after spending a month\nwith cogito, I felt like I was ready for git.  The only thing I miss\nfrom cogito is colorized diff output.  ;-)\n"},{"id":"13557","messageId":"86d5k1y7dp.fsf@blue.stonehenge.com","threadId":"2789","inReplyTo":"20051213035842.GF10371@always.joy.eth.net","subject":"Re: as promised, docs: git for the confused","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-12-13T03:59:30Z","receivedAt":"2005-12-13T03:59:30Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Joshua\" == Joshua N Pritikin <jpritikin@pobox.com> writes:\n\nJoshua> I don't remmeber which documentation I read but after spending a month\nJoshua> with cogito, I felt like I was ready for git.  The only thing I miss\nJoshua> from cogito is colorized diff output.  ;-)\n\nYes, that fits my experience as well.  I also don't see any direct\nsupport for .gitignore files in any of the plumbing.  Am I missing\nsomething there?\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"13558","messageId":"7vzmn5bmlk.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"86d5k1y7dp.fsf@blue.stonehenge.com","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-13T05:19:19Z","receivedAt":"2005-12-13T05:19:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"merlyn@stonehenge.com (Randal L. Schwartz) writes:\n\n> ...  I also don't see any direct support for .gitignore files\n> in any of the plumbing.  Am I missing something there?\n\nNo, you are not missing anything.\n\nThe only Plumbing support is that ls-files takes --exclude-from=\nand --exclude-per-directory= options.  It is up to the Porcelain\nlayer what names to use.\n\nWe agreed upon a convention to use .gitignore as per-directory\nand .git/info/exclude (I think this came from existing practice\nby Cogito back then) as the tree-wide fallback, when these two\nflags were introduced to ls-files, for interoperability across\nPorcelains.\n"},{"id":"13559","messageId":"Pine.LNX.4.64.0512122124290.15597@g5.osdl.org","threadId":"2789","inReplyTo":"7vzmn5bmlk.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-12-13T05:29:47Z","receivedAt":"2005-12-13T05:29:47Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 12 Dec 2005, Junio C Hamano wrote:\n> \n> The only Plumbing support is that ls-files takes --exclude-from=\n> and --exclude-per-directory= options.  It is up to the Porcelain\n> layer what names to use.\n\nThe only _core_ plumbing support is the git-ls-files option, but some of \nthe git helper functions do use it. Notably, \"git add\" and \"git status\" \nboth use those options, which in turn then indirectly means that when \nusing \"git commit\" the commit message template won't list ignored files \netc.\n\nSo the git \"mini-porcelain\" layer does in fact use .gitignore and friends. \n\n\t\tLinus\n"},{"id":"13561","messageId":"439E75CB.1090408@zytor.com","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512122124290.15597@g5.osdl.org","subject":"Re: as promised, docs: git for the confused","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-12-13T07:18:35Z","receivedAt":"2005-12-13T07:18:35Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> So the git \"mini-porcelain\" layer does in fact use .gitignore and friends. \n> \n\n\"Mini-porcelain\"... bidet?\n\n\t-hpa\n"},{"id":"13562","messageId":"7vd5k1bf40.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"7vzmn5bmlk.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-13T08:01:03Z","receivedAt":"2005-12-13T08:01:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n> The only Plumbing support is that ls-files takes --exclude-from=\n> and --exclude-per-directory= options.  It is up to the Porcelain\n> layer what names to use.\n>\n> We agreed upon a convention to use .gitignore as per-directory\n> and .git/info/exclude (I think this came from existing practice\n> by Cogito back then) as the tree-wide fallback, when these two\n> flags were introduced to ls-files, for interoperability across\n> Porcelains.\n\n... and as Linus pointed out already, the barebone Porcelain-ish\nthat ship with git follows that convention as well.\n\nNow those commands are not Porcelain, so please do not call them\nwith any bathroom fixture names ;-).\n"},{"id":"13567","messageId":"861x0hxfn2.fsf@blue.stonehenge.com","threadId":"2789","inReplyTo":"7vd5k1bf40.fsf@assigned-by-dhcp.cox.net","subject":"Re: as promised, docs: git for the confused","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-12-13T13:58:41Z","receivedAt":"2005-12-13T13:58:41Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Junio\" == Junio C Hamano <junkio@cox.net> writes:\n\nJunio> Junio C Hamano <junkio@cox.net> writes:\n>> The only Plumbing support is that ls-files takes --exclude-from=\n>> and --exclude-per-directory= options.  It is up to the Porcelain\n>> layer what names to use.\n>> \n>> We agreed upon a convention to use .gitignore as per-directory\n>> and .git/info/exclude (I think this came from existing practice\n>> by Cogito back then) as the tree-wide fallback, when these two\n>> flags were introduced to ls-files, for interoperability across\n>> Porcelains.\n\nJunio> ... and as Linus pointed out already, the barebone Porcelain-ish\nJunio> that ship with git follows that convention as well.\n\nI see now that grepping \"gitignore\" shows git-add.sh and\ngit-status.sh.  gitignore is indeed doc'ed in git-add.txt, but not in\ngit-status.txt.  Must've snuck in recently.  I'm trying to watch\n\"git-whatchanged -p Documentation/*\", but I miss things sometimes.\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"13578","messageId":"7vpso07l63.fsf_-_@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"861x0hxfn2.fsf@blue.stonehenge.com","subject":"Tip of the day: archaeology","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-13T21:16:04Z","receivedAt":"2005-12-13T21:16:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"merlyn@stonehenge.com (Randal L. Schwartz) writes:\n\n> I see now that grepping \"gitignore\" shows git-add.sh and\n> git-status.sh.  gitignore is indeed doc'ed in git-add.txt, but not in\n> git-status.txt.  Must've snuck in recently.  I'm trying to watch\n> \"git-whatchanged -p Documentation/*\", but I miss things sometimes.\n\nLet me grab this opportunity to demonstrate archaeology tools.\n\n    $ git whatchanged --pretty=oneline \\\n      -S'--exclude-per-directory=.gitignore' git-status.sh\n\nshows the \"Big tool rename\" commit 215a7ad on Sep 7th had it as\n621fa49 blob, and we can see that the revision:\n\n    $ git cat-file blob 621fa49 | grep -B2 gitignore\n            git-ls-files --others \\\n                --exclude-from=\"$GIT_DIR/info/exclude\" \\\n                --exclude-per-directory=.gitignore |\n\nalready had .gitignore support [*1*].  Looking at the big rename\ncommit, we learn git-status.sh used to be called as\ngit-status-script:\n\n    $ git-diff-tree -r -M --name-status 215a7ad | grep status.sh\n    R093\tgit-status-script\tgit-status.sh\n\nDigging further with the old name reveals that it is this commit:\n\n    $ git whatchanged --pretty=oneline \\\n      -S'--exclude-per-directory=.gitignore' git-status-script\n    diff-tree ba966b9... (from 9804b7d...)\n    Teach git-status-script about git-ls-files --others\n    :100755 100755 1999a66... 1696f23... M\tgit-status-script\n    $ git cat-file blob 1696f23 | grep gitignore\n\t    --exclude-per-directory=.gitignore |\n    $ git cat-file blob 1999a66 | grep gitignore\n    $ git log --max-count=1 ba966b9 | head -n 5\n    commit ba966b957908248396402acd785d10ba1da07294\n    Author: Junio C Hamano <junkio@cox.net>\n    Date:   Fri Aug 26 02:12:50 2005 -0700\n\n        Teach git-status-script about git-ls-files --others\n\n\n[Footnote]\n\n*1* Sometimes I wish we had \"cvs co -p\" equivalent.\n\n\t$ git cat-blob rev path\n\nPerhaps?\n"},{"id":"13580","messageId":"Pine.LNX.4.64.0512131351100.4184@g5.osdl.org","threadId":"2789","inReplyTo":"7vpso07l63.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: Tip of the day: archaeology","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-12-13T21:54:44Z","receivedAt":"2005-12-13T21:54:44Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 13 Dec 2005, Junio C Hamano wrote:\n> \n> *1* Sometimes I wish we had \"cvs co -p\" equivalent.\n> \n> \t$ git cat-blob rev path\n> \n> Perhaps?\n\nIsn't \"git-ls-tree rev path\" good enough? Maybe you want to wrap it with\n\n\t#!/bin/sh\n\tgit-ls-tree \"$@\" |\n\t\twhile read mode type sha name\n\t\tdo\n\t\t\tgit-cat-file $type $sha\n\t\tdone\n\nor something? \n\n\t\tLinus\n"},{"id":"13581","messageId":"7vbqzk7i84.fsf@assigned-by-dhcp.cox.net","threadId":"2789","inReplyTo":"Pine.LNX.4.64.0512131351100.4184@g5.osdl.org","subject":"Re: Tip of the day: archaeology","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-13T22:19:39Z","receivedAt":"2005-12-13T22:19:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Tue, 13 Dec 2005, Junio C Hamano wrote:\n>> \n>> *1* Sometimes I wish we had \"cvs co -p\" equivalent.\n>> \n>> \t$ git cat-blob rev path\n>> \n>> Perhaps?\n>\n> Isn't \"git-ls-tree rev path\" good enough? Maybe you want to wrap it with\n>\n> \t#!/bin/sh\n> \tgit-ls-tree \"$@\" |\n> \t\twhile read mode type sha name\n> \t\tdo\n> \t\t\tgit-cat-file $type $sha\n> \t\tdone\n>\n> or something? \n\nExactly.  The point was that we do not ship a prepackaged script\nlike that.\n"}]}