{"thread":{"id":"43371","subject":"Re: [Patch to DRAFT 2 (2/2)] Branching and merging with git","startedAt":"2006-11-18T01:11:34Z","lastAt":"2006-12-15T21:41:56Z","messageCount":11,"participants":["Rene Scharfe","J. Bruce Fields","Junio C Hamano","Johannes Schindelin","linux@horizon.com","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"298019","messageId":"7vslghftix.fsf@assigned-by-dhcp.cox.net","threadId":"43371","inReplyTo":"7virhdh9j8.fsf@assigned-by-dhcp.cox.net","subject":"Re: [DRAFT] Branching and merging with git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-18T01:11:34Z","receivedAt":"2006-11-18T01:11:34Z","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>> (Are there any octopus merges in git's history?  If not, could I ask\n>> for one for pedagogical value?)\n>\n> git.git itself is full of them, but the very first octopus (it\n> actually is a pentapus) is rather nice to watch in gitk:\n>\n> \t211232bae64bcc60bbf5d1b5e5b2344c22ed767e\n\nHaving said that, I think it is not a good idea to talk about\noctopus in introductory documents.  The 'feature' may be unique\nto git and some people might even find it cool, but new people\nshould not be encouraged to use it until they understand the\nramifications.\n\nThe first ever octopus merge was just a bundle of five forked\ndevelopment branches, each of which had only one commit since it\nforked from the common parent.\n\n           .-a-.  \n          .--b--.\n         O---c---X\n          '--d--'\n           '-e-' \n\nThey were independent, un-overlapping changes.  \"diff-tree -c\"\nwould not show anything, and there was no inherent reason that\none change should come before the others, so in that sense,\npresenting this as an octopus was making the history more\ntruthful than pretending one happened before another.\n\nBut octopus has a negative effect on bisecting performance.\nSuppose commit X was bad and commit O was good.  Because X\nbundles five branches into one, and we know one of them\n(hopefully) is what introduced the regression, our task is to\nfind the guilty one commit among five commits.  But in order to\ndo so, we would end up having to test four commits.  That is,\nknowing that a, b and c are Ok does not give us any useful\ninformation to determine which of d or e is the bad one (after\nlearning that a, b and c are Ok, we still need to test d and if\nit turns out to be Ok then we can finally say e is the bad one).\n\nIf I did not do an octopus and laid out the commit ancestry\ngraph this way when I gave them to Linus:\n\n    O--a--b--c--d--e--X\n\nthe same bisect would have asked us check c first.  If it is\ngood, then we do not even have to test a or b.  The linear part\nof the history is what bisect takes advantage of to cut the\nsearch space efficiently, and an octopus actively defeats that.\n\nSo doing an octopus is a wrong thing to do, if there is a\npossibility that something wrong is found later.  So people\nshould not do an octopus unless the component changes are all\ntruely trivial.\n\nIf you want an esoteric topic for an introductory documentation,\nit would be more useful to talk about evil merges (an evil merge\nis a merge commit whose result does not match any of its\nparents).  A good example is found in\n\n\tgit show v1.0.0\n"},{"id":"298070","messageId":"20061120235136.4841.qmail@science.horizon.com","threadId":"43371","inReplyTo":"7vslghftix.fsf@assigned-by-dhcp.cox.net","subject":"[DRAFT 2] Branching and merging with git","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2006-11-20T23:51:36Z","receivedAt":"2006-11-20T23:51:36Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"I tried to incorporate all the suggestions.  There are still a few things\nI have to research, and now I'm worried it's getting too long.  Sigh.\n\nGenerally, it's wonderful when the whole is greater than the sum of\nthe parts.  But trying to explain that is difficult, because you have\nto explain all the parts before you can explain how they work together\nto deliver a feature.\n\nOh, well.  Perhaps I can rearrange this to talk about remote branches\n*after* local merging?\n\nThanks to everyone who commented.\n\n\n* Branching and merging in git\n\nIn CVS, branches are difficult and awkward to use, and generally\nconsidered an advanced technique.  Many people use CVS for a long time\nwithout departing from the trunk.\n\nGit is very different.  Branching and merging are central to effective use\nof git, and if you aren't comfortable with them, you won't be comfortable\nwith git.  In particular, they are required to share work with other\npeople.\n\nThe only things that are a bit confusing are some of the names.\nIn particular, at least when beginning:\n- You create new branches with \"git checkout -b\".\n  \"git branch\" should only be used to list and delete branches.\n- You share work with \"git fetch\" and \"git push\".  These are opposites.\n- You merge with \"git pull\", not \"git merge\".  \"git pull\" can also do a\n  \"git fetch\", but that's optional.  What's not optional is the merge.\n\nAlso, a good habit it to never commit directly to your main \"master\"\nbranch.  Do all work in temporary \"topic\" branches, and then merge them\ninto the master.  Most experienced users don't bother to be quite this\npurist, but you should err on the side of using separate topic branches,\nso it's excellent practice.\n\n\n* A brief digression on command names\n\nAll git commands can be invoked as \"git-foo\" and \"git foo\".  This document\nuses them interchangably.  But you have to ask for the \"git-foo\" man page.\nGit provides a few other ways to get the man page as well:\n\tman git-foo\n\tgit help foo\n\tgit foo --help\n\nGit doesn't have a specialized built-in help system; it just shows you\nthe man pages.\n\nOne outstanding problem with git's man pages is that often the most detail\nis in the command page that was written first, not the user-friendly\none that you should use.  For example, there are a number of special\ncases of the \"git diff\" command that were written first, and the man\npages for these commands (git-diff-index, git-diff-files, git-diff-tree,\nand git-diff-stages) are considerably more informative than the page for\nplain git-diff, even though that's the command that you should use 99%\nof the time.\n\nLikewise, the man page for the incredibly useful \"git show\" command is a\nsterile wasteland; you have to refer to the git-rev-list and git-diff-tree\nman pages to find the many interesting options it supports.\n\n\t\n\"git-foo --help\" often gives you the man page as well, but sometimes\ngives a different help listing.  (Try \"git-rebase --help\" and compare\nit with \"git rebase --help\".)\n\nIf you care, here's why:\n\nThere are over 100 git-* commands.  This has led to some complaints\nabout the clutter in /usr/bin.  So it's now possible to move the git-*\ncommands into a separate directory, and you can either add that directory\nto your $PATH, or always use the \"git\" wrapper to find and invoke them.\n\nThis is kind of academic as, despite the complaints, I don't know anyone\nwho has actually removed the git-* forms from the default $PATH.\n\nSince the wrapper was developed, some simple commands have been made\n\"builtin\", so for example, \"git diff\" is done internally.  There's a\ngit-diff link to retain compatability.\n\n\n* Git's representation of history\n\nAs you recall from Git 101 (or the git(7) man page), git's largest\ndata strucure is the object database, holding exactly four kidnds\nof objects.  Each of them has a globally unique 40-character hex name\n(a.k.a. object IDs) made by hashing its type and contents.  Since this is\nan (effectively unforgeable) cryptographic hash, the name of an object\nidentifies its contents uniquely.  This is what is meant when people\nsay that git's history is immutable; you can erase it and rewrite it,\nbut any alterations will have a different name, and it will be obvious\nto anyone looking that something has been changed.\n\nBlob objects are the simplest: they record file contents, and contain\nuninterpreted bytes.\n\nTree objects record directory contents; they contain file names,\npermissions, and the associated tree or blob object names.\n\nTag objects are shareable pointers to other objects; they're generally\nused to store a digital signature, and generally point to commits.\n(Although you can tag any object, including another tag.)\n\nFinaly, there are commit objects.  Every commit points to (contains the\nname of) an associated tree object which records the state of the source\ncode at the time of the commit, and some descriptive data (time, author,\ncommitter, commit comment) about the commit.\n\nBecause every commit is associated with one tree, it's considered\n\"tree-ish\", and almost anywhere that git expect a tree object, you can\nsupply a commit, and it'll understand.  (Tags on commits are likewise\nconsidered \"commit-ish\", and can be used almost anywhere a commit or\ntree is required.)\n\nMost importantly, each commit contains a list of \"parent commits\", older\ncommits from which this one is derived.  These pointers are what produce\nthe history graph.\n\nTypically only one commit (the initial commit) has zero parents.  It's\npossible to have more than one such commit (if you merge two projects\nwith separate histories), but that's unusual.\n\nMany commits have exactly one parent.  These are made by a normal commit\nafter editing.  From a branching and merging point of view, they're not\ntoo exciting.\n\nAnd then there are commits which have multiple parents.  Two is most\ncommon, but git allows many more.  There's a limit of sixteen in\nthe source code, and the most anyone's ever used in real life is 12,\nwhich was generally regarded as overdoing it.  The famous \"dodecapus\"\nis commit 9fdb62af in the linux kernel repository.\n\n\nFinally, there are references, stored in the .git/refs directory.\nThese are the human-readable names associated with commits, and the\n\"root set\" from which all other commits should be reachable.\n\nThese references are generally divided into two types, although\nthere is no fundamental difference:\n- Tags are references that are intended to be immutable.\n  A tag like \"v1.2\" is a historical record.  Tag references may or may not\n  point to tag objects!  If they do, this is called a \"heavyweight tag\";\n  the tag can hold a digital signature and can be shared between repositores.\n  \"Lightweight tags\" point to commits directly, and are not automatically\n  shared.\n- Heads are references that are intended to be updated.\n  They are invariably \"lightweight.\"  \"Head\" is actually synonymous with\n  \"branch\", although one emphasizes the tip more, while the other directs\n  your attention to the entire path that got there.\n\nEither way, they're just a 41-byte file that contains a 40-byte hex\nobject ID, plus a newline.  Tags are stored in .git/refs/tags, and heads\nare stored in .git/refs/heads.  Creating a new branch is literally just\npicking a file name and writing the ID of an existing commit into it.\n\nThe git programs enforce the immutability of tags, but that's a safety\nfeature, not something fundamental.  You can rename a tag to the heads\ndirectory and go wild.  (But the git-update-ref helper takes care of\na few corner cases involving symlinks.)\n\nThe only limit on branches is clutter.  A number of git commands have\nways to operate on \"all heads\", and if you have too many, it can get\nannoying.  If you're not using a branch, either delete it, or move it\nsomewhere (like the tags directory) where it won't clutter up the list of\n\"currently active heads\".\n\n(Note that CVS doesn't have this all-heads default, so people tend to\nuse longer branch names and keep them around after they've been merged\ninto the trunk.  Old CVS repositories converted to git generally need\nan old-branch cleanup.)\n\nAnother thing that's worth mentioning is that head and tag names can\ncontain slashes; i.e. you're allowed to make subdirectories in the\n.git/refs/heads and .git/refs/tags directories.  See the man page\nfor \"git-check-ref-format\" for full details of legal names.\n\n\n* Naming revisions\n\nCVS encourages you to tag like crazy, because the only other way to\nfind a given revision is by date.  Git makes it a lot easier, so most\nrevisions don't need names.\n\nYou can find a full description in the git-rev-parse man page, but here's\na summary.\n\nFirst of all, every commit has a globally unique name, its 40-digit hex\nobject ID.  It's a bit long and awkward, but always works.  This is useful\nfor talking about a specific commit on a mailing list.  You can abbreviate\nit to a unique prefix; most people find about 8 digits sufficient.\n\n(Subversion is easier yet, because it assigns a sequential number to each\ncommit.  However, that isn't possible in a distributed system like git.)\n\nSecond, you can refer to a head or tag name.  Git looks in the\nfollowing places, in order, for a reference:\n\t1) .git/<name>\n\t2) .git/refs/<name>\n\t3) .git/refs/tags/<name>\n\t4) .git/refs/heads/<name>\n\t5) .git/refs/remotes/<name>\n\t6) .git/refs/remotes/<name>/HEAD\n\nYou should avoid having e.g. a head and a tag with the same name, but\nif you do, you can specify one or the other with heads/foo and tags/foo.\n\nThird, you can specify a commit relative to another.  The simplest\none is \"the parent\", specified by appending ^ to a name.  E.g.  HEAD^\nor deadbeef^.  If there are multiple parents, then ^ is the same as ^1,\nand the others are ^2, ^3, etc.\n\nSo the last few commits you've made are HEAD, HEAD^, HEAD^^, HEAD^^^, etc.\nAfter a while, counting carets becomes annoying, so you can abbreviate\n^^^^ as ~4.  Note that this only lets you specify the first parent.\nIf you want to follow a side branch, you have to specify something like\n\"master~305^2~22\".\n\n\n* Converting between names\n\nGit has three helpers (programs designed mainly for use in shell scripts)\nto convert between global object IDs and human-readable names.\n\nThe first is git-rev-parse.  This is a general git shell script helper,\nwhich validates the command line and converts object names to absolute\nobject IDs.  Its man page has a detailed description of the object\nname syntax.\n\nThe second is git-name-rev, which converts the other way around, giving\na name for the specified commit in terms of the existing references.\nThis searches the references for the closest descendant of the given\ncommit.  If called with the --tags option, it'll search only tags,\nshowing you the next tag on the development path.\n\nThird is git-describe.  This is something like git-name-rev, but\nbackwards: it finds the closest reference that is an ancestor of the\nspecified commit.  Its output is not acceptable git input, but takes\nthe form of either\n\tv1.2\t\t(tag name), or\n\tv1.2-g12345678\t(commit 12345678, whose nearest ancestor is v1.2)\n\ngit-describe's output is intended to be used as a software version\nnumber, something like the \"rcsid\" feature in RCS and CVS.\nBy default, git-describe uses only heavyweight tags for its naming,\nso they are globally unique, but you can ask for it to be more liberal.\n\nGit has chosen not to implement anything like the RCS/CVS \"keyword\nsubstitution\" feature, but you can invoke git-describe from a Makefile\nand incorporate its output into an executable to achieve a similar effect.\n\n\n* Working with branches, the trivial cases.\n\nBy convention, the local \"trunk\" of git development is called \"master\".\nThis is just the name of the branch it creates when you start an empty\nrepository.  You can delete it if you don't like the name.\n\nIf you create your repository by cloning someone else's repository, the\nremote \"master\" branch is copied to a local branch named \"origin\".  You\nget your own \"master\" branch which is not tied to the remote repository.\n\nThere is always a current head, known as HEAD.  (This is actually a\nsymbolic link, .git/HEAD, to a file like refs/heads/master.)  Git requires\nthat this always point to the refs/heads directory.\n\n\tMinor technical details:\n\t1) HEAD used to be a Unix symlink, and can still be though of that\n\t   way, but for Microsoft support, this is now what's called a\n\t   \"symbolic reference\" or symref, and is a plain file containing\n\t   \"ref: refs/heads/master\".  Git treats it just like a symlink.\n\t   There's a git-update-ref helper which writes these.\n\t2) While HEAD must point to refs/heads, it's legal for it to\n\t   point to a file that doesn't exist.\tThis is what happens\n\t   before the first commit in a brand new repository.\n\nWhen you do \"git commit\", a new commit object is created with the old\nHEAD as a parent, and the new commit is written to the current head\n(pointed to by HEAD).\n\n\n* The three uses of \"git checkout\"\n\nGit checkout can do three separate things:\n\n1) Change to a new head\n\n\tgit checkout [-f|-m] <branch>\n   This changes the HEAD symref to point to <branch>, and copies its\n   state to the index and the working directory.\n\n   If a file has unsaved changes in the working directory, this tries\n   to preserve them.  This is a simple attempt, and requires that the\n   modified files(s) are not altered between the old and new HEADs.\n   In that case, the version in the working directory is left untouched.\n\n   A more aggressive option is -m, which will try to do a three-way\n   (intra-file) merge.  This can fail, leaving unmerged files in the\n   index; dealing with this is described later.\n\n   An alternative is to use -f, which will overwrite any unsaved changes\n   in the working directory.  This option can be used with no <branch>\n   specified (defaults to HEAD) to undo local edits.\n\n2) Revert changes to a small number of files.\n\n\tgit checkout [<revision>] [--] <paths>\n   will copy the version of the <paths> from the index to the working\n   directory.  If a <revision> is given, the index for those paths will\n   be updated from the given revision before copying from the index to\n   the working tree.\n\n   Unlike the version with no <paths> specified, this does NOT change\n   HEAD, even if <paths> is \".\".\n\n   The \"--\" is only required if the first <path> could be\n   mistaken for a revision.\n\n3) Create a branch.\n\n\tgit checkout [-f|-m] -b <branch> [revision]\n   will create, and switch to, a new branch with the given name.\n   This is equivalent to\n\tgit branch <branch> [<revision>]\n\tgit checkout [-f|-m] <branch>\n   If <revision> is omitted, it defaults to the current HEAD, in which\n   case no working directory files are altered.\n\n   This is the usual way that one creates a new branch to start work\n   on it, or checks out a revision that does not have an existing head\n   pointing to it.\n\n   Note that you can create a branch at any time up until the git-commit;\n\n\n\n* Deleting branches\n\n\"git branch -d <head>\" is safe.  It deletes the given <head>, but first\nit checks that the commit is reachable from the current HEAD.  That is,\nyou merged the branch in to the current HEAD, or you never did any edits\non that branch.\n\nIt's a good idea to create a \"topic branch\" when you're working on\nanything bigger than a one-liner, but it's also a good idea to delete\nthem when you're done.  The commits are still there in the history.\n\n* Doing rude things to heads: git reset\n\nIf you need to overwrite the current HEAD for some reason, the tool to\ndo it with is \"git reset\".  There are three levels of reset:\n\ngit reset --soft <head>\n\tThis overwrites the current HEAD with the contents of <head>.\n\tIf you omit <head>, it defaults to HEAD, so this does nothing.\ngit reset [<head>]\ngit reset --mixed [<head>]\n\tThese overwrite the current HEAD, and copy it to the index,\n\tundoing any git-update-index commands you may have executed.\n\tIf you omit <head>, it default to HEAD, so there is no change\n\tto the current branch, but all index changes are undone.\ngit reset --hard [<head>]\n\tThis does everything mentioned above, and updates the\n\tworking directory.  This throws away all of your in-progress\n\tedits and gets you a clean copy.  This is also commonly\n\tused without an explicit <head>, in which case the current\n\tHEAD is used.\n\n\n* Using git-reset to fix mistakes\n\n\"Oh, no!  I didn't mean to commit *that*!  How do I undo it?\"\n\nIf you just want to undo a commit, then you can use \"git reset HEAD^\"\nto return the current HEAD to the previous version.  If you want to leave\nthe commit in the index (this only applies to you if you are familiar with\nusing the index; see below), then you can use \"git reset --soft HEAD^\".\n\nAnd if you want to blow away every record of the changes you made,\nyou can use \"git reset --hard HEAD^\"\n\nIf you just want a stupid trivial mistake and want to replace the most\nrecent commit with a corrected one, \"git commit --amend\" is your friend.\nIt makes a new commit with HEAD^ rather than HEAD as its ancestor.\n\nIt's often much easier to use --amend than fiddle around with git-reset.\n\n\n* Fixing mistakes without git-reset\n\ngit-reset has the problem that it doesn't preserve hacking in progress\nin the working directory.  It can leave the working directory alone\n(making everything a \"hack in progress\"), but it can't merge in-progress\nchanges like git checkout.\n\nSo, suppose you've been trying something that should have been simple,\nand made three commits to your main branch before realizing that the\nproblem is harder than you thought, and you want your work so far to be\non a new branch of its own; committing them on the current HEAD (I'll\ncall it \"old\") was a mistake.\n\nYou don't want to erase anything, just rename it.  Make \"new\" a copy of\nthe current \"old\" and move old back to HEAD^^^ (three commits ago).\n\nWhile there are ways to do that using git-reset, but far better is\nto use \"git branch -f\":\n\n\tgit checkout -b new\n\t\tCreate (and switch to) the \"new\" branch.\n\tgit branch -f old HEAD^^^\n\t\tForcibly move \"old\" back three versions.\n\t\t(You could also use old~3 or new^^^ or any synonymous name.)\n\nYou can use a similar trick to rename a branch.  If it's the current\nHEAD, then:\n\n\tgit checkout -b newname\n\tgit branch -d oldname\n\nand if it's not, then\n\n\tgit branch newname oldname\n\tgit branch -d oldname\n\nAn alternative in the latter case is to just use mv on the raw\n.git/refs/heads/oldname file.\n\n\n* How do I check out an old version?\n\nA very common beginning question is how to check out an old version.\nSay you need to compile an old release for test purposes.  \"git checkout\nv1.2\" gives a funny error message.  What's going on?\n\nWell, \"git checkout\" makes the current HEAD point to the head that\nyou specify.  And, as previously mentioned, git requires that it point\nto something in the .git/refs/heads directory.  So you can't do that.\n\nIf you're busy doing things in your working directory, and don't want to\noverwrite your work with an old version, then you can get a snapshot with\nthe (old) git-tar-tree or (new) git-archive commands.  These produce a\ntar file (git-archive can also produce a zip file) which is a snapshot\nof any version you like.  You can then unpack this file in a different\ndirectory and build it.\n\nHowever, if you haven't got any edits in progress, and want to check out\nthe old version into your working directory, just create a temp branch!\n\n\tgit checkout -b temp v1.2\n\nWill do what you want.  This will also do what you want if you have a\nlocal edit (like the \"#define DEBUG 1\" mentioned above) that you want\nto preserve while working on the old version.\n\nYou'll see this in use if you ever use the (highly recommended) git-bisect\ntool.  It creates a branch called \"bisect\" for the duration of the bisect.\n\n(Yes, I have to confess, I sometimes wish that git would enforce the\n\"HEAD must point to .git/refs/heads\" rule when committing (checking in)\nrather than when checking out, but that's the way git has grown up.)\n\n\nNote that if you want *exactly* an old version, with no local hacks,\nmake sure there are none (with \"git status\") when doing this.  It's more\nconvenient if you do it before the checkout, but you'll get the same\nanswer if you ask afterwards.\n\n\nNow, what about the complex case: you have local hacks that you\nwant to keep, but not have polluting the old version?\n\nWell, one way of the other, you'll have to commit it.  If you don't mind\ncommitting your changes to the current branch (\"git commit -a\"), do that.\n\nIf they're not ready to commit, you can commit them anyway, and back\nthem out when you're done:\n\n\tgit commit -a -m \"Temp commit\"\n\tgit checkout -b temp v1.2\n\tmake ; make test ; whatever\n\tgit checkout master\n\tgit branch -d temp\n\tgit reset HEAD^\n\nThis leaves both the working directory and the master head in the states\nthey were in at the beginning.\n\nIf you don't like committing to the master branch, you can make a new one.\nIn this example, it's \"work in progress\", a.k.a. \"wip\":\n\n\tgit checkout -b wip\n\tgit commit -a -m \"Temp commit\"\n\tgit checkout -b temp v1.2\n\tmake ; make test ; whatever\n\tgit checkout wip\n\tgit branch -d temp\n\tgit reset master\n\tgit checkout master\t# Won't change working directory\n\tgit branch -d wip\n\n\n* Examining history: git-log and git-rev-list\n\nIn another example of docs being better on the first command written,\nthe all-purpose utility for examining history is \"git log\", but all of\nthe examples of clever ways to use it are in the git-rev-list man page.\nAnd git-log also has most of git-diff's options.\n\nOther utilities, notably the gitk and qgit GUIs, also use the git-rev-list\ncommand-line options, so it's well worth learning them.\n\n\ngit-rev-list gives you a filtered subset of the repository history.\nThere are two basic ways that you can do the filtering:\n\n1) By ancestry.  You specify a set of commits to include all the\n   ancestors of, and another set to exclude all the ancestors of.\n   (For this purpose, a commit is considered an ancestor of itself.)\n\n   So if you want to see all commits between v1.1 and v1.2, you\n   can specify\n\n   \tgit log ^v1.1 v1.2\n   or, with a more convenient syntax\n   \tgit log v1.1..v1.2\n\n  However, there are times when you want to specify something more\n  complex.  For example, if a big branch that had been in progress since\n  v1.0.7 was merged between v1.1 and v1.2, but you don't want to see it,\n  you could specify any of:\n\n   \tgit log v1.2 ^v1.1 ^bigbranch\n   \tgit log ^bigbranch v1.1..v1.2\n\tgit log ^v1.1 bigbranch..v1.2\n\n  They're all equivalent.  Another special syntax that's sometimes\n  handy is\n\n\tgit log branch1...branch2\n\n   Note the three dots.  This generates the symmetric difference between\n   the two; basically it's a diff between the commits that went into\n   each of them.\n\n   \"git log\" by default pipes its output through less(1), and generates\n   its output from newest to oldest on the fly, so there's no great\n   speed penalty to not specifying a starting place.  It'll generate a\n   few screen fulls more than you look at, but not waste any more effort\n   than that.\n\n2) By path name.  This is a feature which appears to be unique to git.\n   If you give git-rev-list (or git-log, or gitk, or qgit) a list of\n   pathname prefixes, it will list only commits which touch those\n   paths. So \"git log drivers/scsi include/scsi\" will list only\n   commits which alters a file whose name begins with drivers/scsi\n   or include/scsi.\n\n   (If there's any possible ambiguity between a path name and a commit\n   name, git-rev-list will refuse to proceed.  You can resolve it by\n   including \"--\" on the command line.  Everything before that is a\n   commit name; everything after is a path.)\n\n   This filter is in addition to the ancestry filter.  It's also rather\n   clever about omitting unnecessary detail.  In particular, if there's\n   a side branch which does not touch the given paths, then the entire\n   branch, and the merge at the end, will be removed from the log.\n\nYou can additionally limit the commits to a certain number, or by date,\nauthor, committer, and so on.\n\nBy default, \"git log\" only shows the commit messages, so it's important to\nwrite good ones.  Other tools compress commit messages down to\nthe first line, so try to make that as informative as possible.\n\n(\"git show\" is the standard tool for examining a single commit,\nand it does show \n\n\n* History diagrams\n\nWhen talking about various situations involving multiple branches,\npeople often find it handy to draw pictures.  Gitk draws nice pictures\nvertically, but for e-mail, ASCII art drawn horizontally is often easier.\nCommits are shown as \"o\", and the links between them with lines drawn with\n- / and \\.  Time goes left to right, and heads may be labelled with names.\n\nFor example:\n\n         o--o--o <-- Branch A\n        /\n o--o--o <-- master\n        \\\n         o--o--o <-- Branch B\n\nIf someone needs to talk about a particular commit, the character \"o\"\nmay be replaced with another letter or number.\n\n\n* Trivial merges: fast-forward and already up-to-date.\n\nThere are two kinds of merge that are particularly simple, and you will\nencounter them in git a great deal.  They are mirror images.\n\nSuppose that you are working on branch A and merge in branch B, but no\nwork has been done to branch B since the last time you merged, or since\nyou spawned branch A from it.  That is, the history looks like\n\n\n o--o--o--o <-- B\n           \\\n\t    o--o--o <-- A\nor\n o--o--o--o--o--o <-- B\n           \\     \\\n\t    o--o--o--o--o <-- A\n\nIf you then merge B into A, A is described as \"already up to date\".\nIt is already a strict superset of B, and the merge does nothing.\n\nIn particular, git will not create a dummy commit to record the fact that\na merge was done.  It turns out that are a number of bad things that would\nhappen if you did this, but for now, I'll just say that git doesn't do it.\n\n\nNow, the opposite scenario is the \"fast-forward\" merge.  Suppose you\nmerge A into B.  Again, A is a strict superset of B.\n\nIn this case, git will simply change the head B to point to the same\ncommit as A and say that it did a \"fast-forward\" merge.  Again, no commit\nobject is created to reflect this fact.\n\nThe effect is to unclutter the git history.  If I create a topic branch to\nwork on a feature, do some hacking, and then merge the result back into\nthe (untouched!) master, the history will look just like I did all the\nwork on the master directly.  If I then delete the topic branch (because\nI'm done using it), the repository state is truly indistinguishable.\n\nWhile the topic branch existed, you could have done something to the\nmaster branch, in which case the final merge would have been non-trivial,\nbut if that didn't happen, git produces a simple, easy-to-follow linear\nhistory.\n\nSome people used to heavyweight branches find this confusing; they\nthink a merge is a big deal and it should be memorialized, but there\nare actually excellent reasons for doing this.\n\nThe most important one is that a fit of merging back and forth will\neventually end.  Suppose that branches A and B are maintained by separate\ndevelopers who like to track each other's work closely.\n\nIf the fast-forward case did create a commit, then merging A into B\nwould produce\n\n o--o--o--o---------o <-- B\n           \\       /\n\t    o--o--o <-- A\nthen merging B into A would produce:\n o--o--o--o---------o <-- B\n           \\       / \\\n\t    o--o--o---o <-- A\n\nand further merges would produce more and more dummy commits, all without\never reaching a steady state, and without making it obvious that the\ntwo heads are actually identical.\n\nSince history lasts forever, cluttering it up with unimportant stuff is a\nburden to all future users, and not a good idea.  Allowing the merge of a\nbranch to be seamless in the simple case encourages lightweight branches.\nIf you _might_ need a separate branch, create it.  If it turned out that\nyou didn't, it won't make a difference.\n\n\n* Exchanging work with other repositories\n\nThe basic tools for exchanging work with other repositories are \"git\nfetch\" and \"git push\".  The fact that \"git pull\" is not the opposite of\n\"git push\" is often confusing to beginners (it's a superset of git fetch),\nbut that's the terminology that has grown up.\n\nThe unit of sharing in git is the branch.  If you've used branches in\nCVS, you'll be familiar with using \"CVS update\" to pull changes from your\n\"current branch\" in the repository into your working directory.\n\nIn Git, you don't pull into the working directory, but rather into a\ntracking branch.  You set up a branch in your repository which will be\na copy of the branch in the remote repository.  For example, if you use\n\"git clone\", then the remote \"master\" branch is tracked by the local\n\"origin\" branch.\n\nThen, when you do a \"git fetch\", git fetches all of the new commits\nand sets the origin head to point to the newly fetched head of the\nremote branch.\n\nBy default, git checks that this is a trivial fast-forward merge, that\nis not throwing away history.  If it finds something like:\n\no--o--o--o--o--o <-- remote master\n       \\\n        o <-- Local origin\n\nIt will complain and abort the fetch.  This is usually a warning that\nsomething has gone wrong - in particular, you forgot that this was\nsupposed to be a tracking branch and committed some work to it - and it\naborts before throwing your work away.\n\nHowever, sometimes the remote git user will have a branch name that they\ndelete and re-create frequently.  There are plenty of reasons to do this.\nThe most common is doing a \"test merge\" between various branches in\nprogress.  They're all unfinished, so the developer of branch A doesn't\nwant to merge in all the new bugs in branch B, but a tester might want\nto create a merged version with both sets of bugs for testing.\n\nThe merged version is not intended to be a permanent part of history -\nit'll get deleted after the test - but it can still be useful to have\na draft copy.\n\nIn this case, you can mark the source branch with a leading \"+\", to\ndisable this sanity check.  (See the git-fetch man page for details.)\n\nNote that in this case, you should specifically avoid merging from such\na branch into any non-test branches of your own.  It is, as mentioned,\nnot intended to be a permanent part of history, so it would be rude\nto make it part of your permanent history.  (You still might want to\ntest-merge it with your work in progress, of course.)\n\nThe fact that you should know to treat such branches specially is why\ngit doesn't try to automatically cope with them.\n\n\n* Alternate branch naming\n\nThe original git scheme mixes tracking branches with all the other heads.\nThis requires that you remember which branches are tracking branches and\nwhich aren't.  Hopefully, you remember what all your branches are for,\nbut if you track a lot of remote repositories, you might not remember\nwhat every remote branch is for and what you called it locally.\n\nAn alternative convention has been developed (which may become the\ndefault in future), that places copies of the remote servers' heads\nunder .git/refs/remotes/<server>/<branch>.\n\nThen you can refer to\n\nIf you use \"git-line --use-separate-remote\", it will set\n\nIf you want to use the \"separate remotes\" tracking branch\nThere's an alternate way, using the --use-separate-remote option\nto git-clone.  This sets up a copy of the remote server's heads\nunder .git/refs/remotes/origin/<name>.  Then you can refer to\n\"origin/<branch>\" whenever you want.\n\nBecause the branch names are got under .git/refs/heads, the git\ntools will not let you commit to the branch.\n\n* Remotes files\n\nYou can specify what to fetch on the git-fetch command line.\nThat is, you can type\n\n\tgit fetch <url> src1:dst1 src2:dst2\n\nto fetch the given remote heads src1 and src2\nHowever,\nif you intend to monitor another repository on an ongoing basis,\nit's generally easier to set up a short-cut by placing the options in\n.git/remotes/<name>.\n\nThe syntax is explained in the git-fetch man page.  When this is st\nup, \"git fetch <name>\" will retrieve all the branches listed in the\n.git/remotes/<name> file.  The ability to fetch multiple branches at\nonce (such as release, beta, and development) is an advantage of using\na remotes file.\n\ngit-fetch with no argument uses the default file .git/remotes/origin.\nIf you have a single primary \"upstream\" repository that you sync to,\nplace it in the origin remotes file, and you can just type \"git fetch\"\nto get all the latest changes.\n\nNote that branches to fetch are identified by \"Pull: \" lines in the\nremotes file.  This is another example of the fetch/pull confusion.\ngit-pull will be explained eventually.\n\nIf you want to follow this convention when manually adding\nbranches to track, just supply .git/-relative branch names:\n\n\tPull: refs/heads/master:refs/remotes/origin/master\n\tPull: refs/heads/beta:refs/remotes/origin/beta\n\tPull: refs/heads/alpha:refs/remotes/origin/alpha\n\n[TODO: Explain the git config file alternative.  I need to write a section\non the config file itself first.]\n\n* Cloning\n\nIf you want to watch a project that's hosted on a git server, the easiest\nway is to use \"git clone\".\n\ngit-clone creates a new repository, sets up a remotes file to reack\nevery branch in the remote repository, and fetches all those branches.\nBy default, it maps them to local heads as follows:\n\n- The remote \"master\" is tracked by the local \"origin\"\n- The local \"master\" is made a copy of that.\n- The remote \"origin\" is not tracked at all.\n- All other heads are tracked by local heads of the same name.\n\nIf you use git-clone --use-separate-remote, then a different,\nsimpler convention for remote heads will be used:\n\n- Every remote <head> is tracked by .git/refs/remotes/origin/<head>.\n\nEither way, the fetch information is all placed in the .git/remotes/origin\nfile, which (as mentioned above) is the default used by git-fetch if no\nargument is supplied.\n\n\n* Fetching without tracking (advanced)\n\nWhenever a fetch is done, the fetched heads are also stored in\n.git/FETCH_HEAD.  This is for use by later merging (coming up\nreally soon, promise!).  In fact, it's possible to fetch without\nwriting to any local heads at all.  If you just\n\n\tgit fetch <url> src1 src2\n\nThen the fetch will be done, but the results will be written nowhere\nbut .git/FETCH_HEAD.  This is actually the earliest form of git_fetch\nimpllemented; everything else is a later addition.  It's not something\nyou'd do on purpose much, except as part of a script that uses FETCH_HEAD,\nbut it's worth mentioning it in case you type it and wonder what the\nheck happened.\n\n\n* Remote tags\n\nWhen you fetch to a tracking branch, git-fetch also fetches every\nheavyweight tag (one that involves an actual tag object) that\npoints to a commit reachable from the branch head and installs a\ncopy locally.\n\nIt will never overwrite a pre-existing tag of the same name.\nThis means that if you publish a heavyweight tag, and then try\nto change it, people who fetched the old tag won't see the change!\n\nThis is perhaps an excessively liberal policy, but it has worked\nwell in practice so far.  Still, it does mean that you should\nthink about who you fetch code from.\n\nSince tags can be PGP-signed, one option would be to verify them\nbefore installing them locally.\n\nIn case it helps, the primitive to get a list of remote heads and tags\nis git-ls-remote.  It's used by git-clone to get the list of heads to\ntrack, and can be used manually to see what's been added since then that\nyou might be interested in tracking.\n\n\n* Git network protocols\n\nThere a few basic ways to share a git repository over the 'net, which\nbreak down into \"dumb\" protocols that just copy files, and the \"smart\"\ngit native protocol that can deliver just the objects that you need.\n\n1) http protocol.  This is sub-optimal, but may be all you have.\n   The challenge with this is that you have to pack your repository\n   into chunks that are neither too big (because you have to download\n   all of a chunk to download any of it) not too small (because the\n   http request overhead would kill you).  So think carefully about\n   how often you run git-repack, and don't run git-repack -a.\n\n   http clients also need some extra index information to help them\n   find which pack files they need.  git-update-server-info is the\n   command that generates these files, but it's run automatically\n   from git-repack, so it's not too important to know.\n\n2) rsync protocol.  This is basically an alternative to http, and\n   has the same strictures and limitations.\n\n3) The git protocol.  This is represented with a git:// URL, and talks\n   to a dedicated git daemon (see the git-daemin man page) on the\n   remote machine.  It uses TP port 9418 by default.  This is a smart\n   protocol that understands the git format and does sophisticated\n   wire compression.\n\n   It uses more CPU on the server, but less bandwidth.  And it doesn't\n   require any special care when repacking.  git-daemon is purposefully\n   written to provide read-only service.\n\n4) The git protocol over ssh.  This is a git+ssh:// URL; ssh:// is\n   accepted as a synonym.  It has the same efficiency issues as\n   plain git.  If you want to limit ssh users to just the git commands\n   necessary to share work, git provides a git-shell command that can\n   be used as a very limited login shell.\n\nIt's been reported that using http or rsync for the initial clone is\nfaster than the smart git protocol, because the smarts are wasted\nwhen you just need to download everything.  Then you can go into\nthe remotes/origin file and edit the URL line to git:// for later\nsmart access.\n\nBut unless you want to bother with that very minor optimization,\njust remember to use the git native protocol whenever possible.\n\n\n* Exchanging work with other repositories, part II: git-push\n\nIt's simpler to set up git sharing on a pull basis.  If your source\ncode isn't secret, you can set up a public read-only server very easily\n(see the git-daemon man page for details), and have other fetch from that.\n\nHowever, N developers all pulling from each other is an N^2 mess.\nSome centralization helps.\n\nOne way is to have a central coordinator (like Linus) who pulls from\nall of the developers, and who they in turn pull from.\n\nThe other is familiar to users of centralized VCSs: have a central\nrepository that people can push to.  This generally requires an ssh login\non the server.  You can use git-shell as the login shell if all you want\nto allow the account to do is git fetch and push.  (You can use the hook\nscripts to enforce rules about who's allowed to do what to which branch.)\n\nGit-push to the remote machine works exactly like git-fetch from the\nremote machine.  The objects are moved over, and the branches pushed to\nare fast-forwarded.  If fast-forward is impossible, you get an error.\n\nSo if you have multiple people committing to a branch on the server,\nyou will not be allowed to push if someone has pushed more to that branch\nsince last time you fetched it.\n\nYou have to fix the problem locally, and re-try the push when you've\ngot a new head that includes the most recently pushed work as an ancestor.\n\nThis is exactly like \"cvs commit\" not working if your recent checkout\nwasn't the (current) tip of the branch, but git can upload more than\none commit.\n\nThe simplest way to resolve the conflict is to merge the remote head with\nyour local head.  Alternatively, you can rebase your work to the new\nhead.  (See below for details.)\n\nIn either case, this is easiest if you have different local branches\nfor fetching the remote repository and for pushing to it.\n\nThat is, you have one head that just tracks the master repository's\nmain branch, and another that you add your work to, and push from.\nIt makes resolving conflicts between the two much easier if you\nhave a name for each of them.\n\nLike git-fetch, you can specify everything on the command line:\n\n\tgit-push <url> src1:dst1 src2:dst2 src3:dst3\n\nto upload the local branches src1, src2 and src3 to the corresponding\nremote branches, or you can create a .git/remotes/<name> file.\nThe URL: and any Push: lines in the file are \n\n(If you need different ssh options for different hosts you push to,\nset them up in a .ssh_config file.  You can even have different\noptions for the same host, as .ssh_config lets you specify \"Host alias\"\nand \"HostName real.dom.aim\".)\n\n\nAnother use for git-push, even for a solo developer, is sharing your work\nwith the world.  You can set up a public git server on a high-bandwidth\nmachine (possibly rented from a hosting service) and then push to it to\npublish something.  This also helps keep your private development\nbranches private; git-daemon doesn't have a way to limit which\nbranches it exposes to which people.\n\n\n* Merging (finally!)\n\nI went through everything else first because the most common merge case\nis local changes with remote changes.  Not that you can't merge two\nbranches of your own, but beginners will encounter the local/remote\ncase first.\n\nThe primitive that does the merging is called (guess what?) git-merge.\nAnd there's nothing too terribly wrong with using it.\nHowever, it's usually easier to use the git-pull wrapper.  This merges\nthe changes from some other branch into the current HEAD and generates\na commit message automatically.\n\ngit-merge lets you specify the commit message (rather than generating it\nautomatically), but that's about it.\n\nThe basic git-pull syntax is\n\n\tgit-pull <repository> <branch>\n\nThe repository can be any URL that git supports.  Including, particularly,\na local file.  So to do a simple local merge, you just type\n\n\tgit-pull . <branch>\n\nSo after doing some hacking on branch \"foo\", you would\n\n\tgit checkout master\n\tgit pull . foo\n\nand ba-boom, all is done.\n\n\nNow, you can also specify a remote repository to merge from, using a\ngit://, http:// or git+ssh:// URL.  This is what Linus does all day\nlong, and why the git-pull tool is optimized to allow that.  It uses\ngit-fetch to fetch the remote branch without assigning it a branch name\n(as mentioned above, it gets the magic name FETCH_HEAD), and them merges\nit into the current HEAD directly.\n\nThere is absolutely nothing wrong with doing that, but beginners often\nfind it confusing to have a single short command do quite so much.\nAnd if you are working closely with someone, it's often more convenient\nand less confusing to keep local tracking branches.  Then you can\n\n\tgit fetch\t\t# Fetches 'origin'\n\tgit pull . origin\n\nIt's also possible to give just a single remotes file name to git-pull:\n\n\tgit pull origin\n\nThat does a git fetch, updating all of the listed branches as usual,\nthen merges the _first_ listed branch into HEAD.  It would be more\ncinsistent to merge all the branches, but that's almost never what\nyou want.\n\nBy the way: don't blink, you might miss it!  As I mentioned, pulling is\na very big part of Linus's daily routine, and he's made sure it's fast.\n(Actually, you cant miss all the output it produces.)\n\n\nJust to clarify, because people often get confused:\n\ngit-pull is a MERGING tool.  It always does a merge, as well as an optional\nfetch.  If you just want to LOOK at a remote branch, use git-fetch.\n\n\n* Undoing a merge\n\nIf you discover that a merge was a mistake, it can be undone just like\nany other commit.  The HEAD you merged to is the first parent, so just do\n\n\tgit reset --hard HEAD^\n\nSince your local git repository is private, it's easy to un-commit;\nit's your own private infinite undo.  It's only when you publish\nyour branch that\n\nThis is why Linus likes a git-pull command that does so much in one shot;\nif he doesn't like what he pulls, it's easy to undo.\n\n\n* How merging operates\n\nGit uses the basic three-way merge.  First, it applies it to file names,\nthen to whole files, and then to lines within files.\n\nTo do a three-way merge, you need three versions of a file.  The versions\nA and B you want to merge, and a common ancestor, commonly called O.\nThat is, history proceeds something like:\n\n         o--o--A\n        /\n o--o--O\n        \\\n\t o--B\n\nThe basic idea is \"I want the file O, plus all the changes made from O\nto A, plus all the changes made from O to B.\"  Since the cases where one\nof A or B is a direct ancestor of the other have already been disposed\nof, the three commits must be different.\n\nFor each file, there are a few cases that are trivial, and git gets\nthese out of the way immediately:\n\n- If A and B are identical, the merged result is obvious.\n- If O and A are the same, then the result should be B.\n- If O and B are the same, then the result should be A.\n\nIn the completely trivial case when O, A and B are the same, then\nall three rules apply, they all produce the same obvious result.\n\nGit automatically finds the masrge base O as the most recent\ncommon ancestor of the heads A and B to be merged.\n\nWhen doing a merge, git uses the above 2-out-of-3 merging rules\nthree times:\n\nFirst, the rules are applied to file renames.  So if foo.c is renamed\nto bar.c on branch A, then branch B's foo.c will be merged with it\nto produce the result.\n\nSecond, they're applied to whole files.  If two out of three entire\nfiles are identical, there's nothing more to do.  Since the name of\na blob object uniquely identifies its contents, this lets git do a\nconsiderable amount of merging without even looking at the file contents.\n\nFinally, any files where all three versions are different are loaded\ninto the index file, with the same file name but marked \"stage 1\",\n\"stage 2\", and \"stage 3\", and the classic line-based three-way merge\nis used to resolve the mess,  This looks for isolated \"hunks\" of change\nand uses the same 2-out-of-3 rules to resolve each hunk separately.\n\nOnly if all three commits have differing hunks that overlap (or come\nso glose that git can't be sure) is git unable to automatically resolve\nthe problem.  This requires manual correction, as described below.\n\nIf the merge goes well, it is automatically comitted and the HEAD branch\nupdated to point to the new commit.\n\n\n* Merge subtleties (advanced)\n\nAs mentioned before, the merge base is the most recent common ancestor\nof A and B.  The only problem is, that's not necessarily unique!\n\nThe classic confusing case is called a \"criss-cross merge\", and looks\nlike this:\n\n         o--b-o-o--B\n        /    \\ /\n o--o--o      X\n        \\    / \\\n\t o--a-o-o--A\n\nThere are two most-recent common ancestors of A and B, marked a and b\nin the graph above.  And they're not the same.  You could use either\none and get reasonable results, but how to choose?\n\nThe details are too advanced for this discussion, but the default\n\"recursive\" merge strategy that git uses solves the answer by merging\na and b into a temporary commit and using *that* as the merge base.\n\nOf course, a and b could have the same problem, so merging them could\nrequire another merge of still-older commits.  This is why the algorithm\nis called \"recursive.\"  It's been tested with pathological conditions,\nbut multiply nested criss-cross merges are very rare, so the recursion\nisn't a performance limit in practice.\n\n(This can lead to occasional confusing messages about merge conflicts\nthat aren't real.  That's because git computes the full merge base,\nbut if the conflicting file is actually identical in A and B, the\nmessed-up version in O doesn't matter.)\n\n\n* Alternate merge strategies (advanced)\n\nIn every version control system prior to git, the merging algorithm was\nburied deep in the bowels of the software, and very difficult to change.\nOne of particularly nice things that git did was allow for easily\nreplaceable \"merge strategies\".  Indeed, you can try multiple merge\nstrategies, and the fallback - print an error message and let the user\nsort it out - can be thought of as just another merge strategy.\n\nEnabling this is why the index is so important to git.  It provides a\nplace to store an unfinished merge, so you can try various strategies\n(including hand-editing) to finish it.\n\nThere are two non-default strategies that have their uses in special\ncircumstances.\n\n\n* Octopus merge (advanced)\n\nThe first is the \"octopus\" stratgy.  This is special because it can do\na three- or more-way merge.  See 5401f304 in the git repository for\nan example.  (Run gitk, double-click on the \"SHA1 ID\" box to select\nwhat's already there, enter \"5401f304\" instead, and click \"Goto\".)\n\nThe octopus strategy is invoked automatically when you specify more\nthan one branch at a time to merge in with \"git pull\".  It can't handle\ncomplicated overlaps and file renames as well as the 2-way recursive\nstrategy, but if you have a number of simple, independent changes that you\nwant to merge together, an octopus merge is the obvious way to document\nthe fact that they're truly independent.\n\nThe only downside to using an octopus to combine a number of simple\nchanges is that any merge makes git-bisect's job harder.  If you have\na development history like\n\n    /-b-\\\n   /     \\\n  | /-c-\\ |\n  |/     \\|\n--a---d---g--\n  |\\     /|\n  | \\-e-/ |\n   \\     /\n    \\-f-/\n\nAnd you know that a works but g doesn't, there's no way to do a binary\nsearch on b through f; they have to be searched linearly.  This is\nno harder to bisect, and a lot nicer-looking than the equivalent with\n2-way merges:\n\n    /-b\n   /   \\\n  | /-c-g\n  |/     \\\n--a---d---h--i--j--\n  |\\        /  /\n  | \\-e----/  /\n   \\         /\n    \\-f-----/\n\nBut if they were just done one after the other, you'd have\n\n--a--b--c--d--e--f--\n\nWhich may imply a non-existent dependency between the changes, but\nis a bit simpler.  Still, the first octopus merge in git's own development\n(211232ba) is of this form.  It's a matter of taste.\n\nFor the beginner, the important thing to know is that you never *need*\nan octopus.\n\n   \n* \"Ours\" merge (advanced)\n\nThe other merge strategy that is surprisingly useful is specified with\nthe \"-s ours\" option to git-pull.\n\nThis strategy instructs git that the merged result should be the same\nas the current HEAD.  Any other branches are recorded as parents, but\ntheir contents are ignored.\n\nWhat the heck is the use of that?  Well, it lets you record the fact\nthat some work has been done in the history, and that it shouldn't be\nmerged again.  For example, say you write and share a popular patch set.\nPeople are always merging it in to their local source trees.  But then\nyou discover a much better way to achieve the goal of that patch set, and\nyou want to publish the fact that the new patch supersedes the old one.\n\nIf you developed the new set starting from the old one, that would happen\nautomatically.  But another way to achieve the same goal is to merge the\nold branch it in using the \"ours\" strategy.  Everyone else's git will\nnotice that the patch is already included, and stop trying to merge it in.\n\n\n* When merging goes wrong\n\nThis is the fun part.  Git's default recursive-merge strategy is pretty\nclever, but sometimes changes truly do conflict and need manual fix-up.\n\nWhen git is unable to complete a merge, it leaves the three different\nversions in the index and places a file with CVS-style conflict markers\nin the working directory.\n\nAs long as there is a \"staged\" file like this in the index, you will\nnot be able to commit.  You must resolve the conflict, and update the\nindex with the resolved versions.  You can do this one at a time with\ngit-update-index, or at the end by giving the files as arguments to\ngit-commit.\n\nDoing them one at a time is probably safest; checking in a file which\nstill has conflict markers makes a bit of a mess.  Git will still use\nthe automatically generated commit message when you finally commit.\n(It's stashed in .git/MERGE_MSG, if you care.)\n\nNote that \"git diff\" knows how to be useful with a staged file.\nBy default, it displays a multi-way diff.  For example, suppose I take a\n(slightly buggy) hello.c:\n\n--- hello.c ---\n#include <stdio.h>\n\nint main(void)\n{\n\tprintf(\"Hello, world!\");\n}\n--- end ---\n\nNow, suppose that in branch A, I fix some bugs - add the missing newline\nand \"return 0;\".  In branch B, I display my angst and change it to\n\"Goodbye, cruel world!\".  When I try to merge A into B, obviously I'll\nget a conflict.  The resultant file, with conflict markers, looks like:\n\n--- hello.c ---\n#include <stdio.h>\n\nint\nmain(void)\n{\n<<<<<<< HEAD/hello.c\n        printf(\"Goodbye, cruel world!\");\n=======\n\tprintf(\"Hello, world!\\n\");\n\treturn 0;\n>>>>>>> edadc53fc7a8aef2a672a4fa9d09aa16f4e14706/hello.c\n}\n--- end ---\n\nand the result of \"git diff\" is\n\ndiff --cc hello.c\nindex 4b7f550,948a5f8..0000000\n--- a/hello.c\n+++ b/hello.c\n@@@ -3,5 -3,6 +3,10 @@@\n  int\n  main(void)\n  {\n++<<<<<<< HEAD/hello.c\n +      printf(\"Goodbye, cruel world!\");\n++=======\n+       printf(\"Hello, world!\\n\");\n+       return 0;\n++>>>>>>> edadc53fc7a8aef2a672a4fa9d09aa16f4e14706/hello.c\n  }\n\nNotice how this is not a standard diff!  It has two columns of diff\nsymbols, and shows the difference from each of the ancestors to the\ncurrent hello.c contents.  I can also use \"git diff -1\" to compare\nagainst the common ancestor, or \"-2\" or \"-3\" to compare against each of\nthe merged copies individually.\n\nIn any case, I have to replace the lines from <<<<<<< to >>>>>>> with\ncorrect code.  Then, unless I'm feeling really brave, I should probably\ndo a test compile.  Suppose I fix it to read:\n\n--- hello.c ---\n#include <stdio.h>\n\nint\nmain(void)\n{\n        printf(\"Goodbye, cruel world!\\n\");\n\treturn 0;\n}\n--- end ---\n\nWhen I'm done, another \"git diff\" convinces me that I haven't forgotten\nany conflict markers anywhere like a comment that doesn't get compiled,\nand I can do\n\n\tgit commit -a\n\nThis then prompts me to edit the commit message, but there's a\ndifference; there's something already written:\n\n--- .git/COMMIT_EDITMSG ---\nMerge branch 'A' into B\n\nConflicts:\n\n        hello.c\n#\n# It looks like you may be committing a MERGE.\n# If this is not correct, please remove the file\n#       .git/MERGE_HEAD\n# and try again\n#\n\n# Please enter the commit message for your changes.\n# (Comment lines starting with '#' will not be included)\n# On branch refs/heads/B\n# Updated but not checked in:\n#   (will commit)\n#\n#       modified: hello.c\n--- end ---\n\nThis is the automatically generated merge message and a reminder\nto future readers of what had to be manually fixed.\n\nIn many cases, this is fine, and you can save it and complete the\ncommit.  Or you can add something about the merge if it needs saying.\n\nWhen I'm done, if I don't need branch A any more, I can\n\n\tgit branch -d A\n\n\n* More on fixing broken merges\n\nOften, a merge conflict is a simple textual issue that git's built-in\nmerge couldn't quite handle, like two #include additions in the same\nplace, and it doesn't know that the order doesn't actually matter.\n\nBut sometimes, you have real conceptual conflicts between two changes,\nand it's not clear what to do.  There are a number of ways to look\nthrough history to see what's going on.\n\n\tgit log --merge\n\nwill show you all the commits that\n1) touch files that are unresolved (staged) in the index, and\n2) differ between the branches being merged.\n\nBy default, this only shows the commit messages, but you can\nadd all the usual git-log options, like -p to see the patches\nthemselves.\n\nNote that this doesn't show you which branch each commit is on,\nbut it's still often useful to see what someone was trying to\ndo that caused the problem.\n\nYou can, of course, add a pathname limiter argument to further restrict\nthe commits being shown.\n\n\n* Redoing a merge in case of push conflicts.\n\nWhen pushing to an upstream repository, the usual procedure is\nto merge the remote head and your new development into a push head,\nand then push it to the remore repository.  That is, your work looks\nlike this (\"a\" commits are your work, \"o\" commits are other people's):\n\n--o--o\n      \\\n       a--a--a <-- development\n\nAnd suppose that the upstream repository has grown to\n\n--o--o--o--o--o <-- upstream\n\nSo you fetch it:\n\n--o--o--o--o--o <-- from-upstream\n      \\       \n       a--a--a <-- development\n\nAnd merge it:\n\n--o--o--o--o--o <-- from-upstream\n      \\        \\\n       a--a--a--a <-- to-upstream\n              \n\nAnd now you can push it upstream, which will be a simply\nfast-forward merge:\n\n--o--o--o--o--o\n      \\        \\\n       a--a--a--a <-- upstream\n\nHowever, if someone else has pushed in the meantime, your push will fail\nbecause it can't fast-forward:\n\n          b--b--b <-- upstream\n         /     /\n--o--o--o--o--o\n      \\        \\\n       a--a--a--a <-- to-upstream\n\nThe obvious solution is to re-merge the upstream branch and push again:\n\n          b--b--b\n         /     / \\\n--o--o--o--o--o   \\\n      \\        \\   \\\n       a--a--a--a---a <-- to-upstream\n\nBut that puts more merge commits in the history than necessary.\nBetter is to re-fetch and re-do the merge:\n\n          b--b--b\n         /     / \\\n--o--o--o--o--o   \\\n      \\            \\\n       a--a--a------a <-- to-upstream\n\nThis is just a matter of (starting from the to-upstream branch)\n\n\tgit fetch\t\t# Fetches \"from-upstream\"\n\tgit-reset --hard from-upstream\n\tgit pull . development\n\tgit push \n\n\n* Alternatives to merging\n\nThe bigger and more active your source tree, the more important it is to\nkeep the history reasonably clean.  Just because git can do a merge in\nunder a second doesn't mean that you should do one daily.  When you look\nback at a feature's development history, you'd like to see meaningful\nchanges recorded and not a lot of meaningless ones.\n\nAnother nice thing to keep out of the published history is commits that\ndon't compile or are catastrophically buggy.  These makes git-bisect\nharder to use, and once you've experienced the joys of git-bisect when\ntracking down a newly introduced bug, you'll appreciate why it's good\nto keep the public history clean.\n\nNow, once you have shared a commit with others, and they have incorporated\nit into their development, it becomes impossible to undo.  But git\nprovides tools that are useful for \"rewriting history\" before public\nrelease.  These can be used to edit a commit for publication.\n\n\n* Test merging\n\nOne way to keep the history clean is to simply not merge other branches\ninto your development branch.  If you want to use your new features and\nother people's code changes, make a test merge and use that, but don't\nmake that merge part of your branch.\n\nThis is slightly more work (you have to change to a test branch and do\nyour merging there), but not very much.\n\nSometimes, when doing this, a conflict appears between your changes and\nsomeone else's development.  If you get tired of fixing the same conflict\nevery time you do a test merge, have a look at the git-rerere tool.\nThis remembers resolved conflicts and tries to apply the same resolution\npatch the next time.\n\nIt's written specifically to help you not do an extra merge unnecessarily.\nAlthough its man page is well worth reading, you never invoke git-rerere\nexplicitly; it's invoked automatically by the merge and patch tools if\nyou create a .git/rr-cache directory.\n\n* Cherry picking\n\nIf you have a series of patches on a branch, but you want a subset\nof them, or in a different order, there's a handy utility called\n\"git-cherry-pick\" which will find the diff and apply it as a patch to\nthe current HEAD.  It automatically recycles the commit message from\nthe original commit.\n\nIf the patch can't be applied, it leaves the versions in the index and\nconflict markers in the working directory just like a failed merge.\nAnd just like a merge, it remembers the commit message and provides it\nas a default when I finally commit.\n\nNote that this can only work on a chain of single-parent commits.\nIf a commit has multiple parents, there's no single patch to apply.\n\n\nYou can get the list of commits on a branch with git-log or git-rev-list,\nbut for more complex cases, the git-cherry tool is designed to generate\nthe list of commits to merge.  It has a rather neat approximate-match\nfunction built in which identifies patches that appear to already be\npresent in the target branch.\n\n\n* Rebasing\n\nA special case of cherry-picking is if you want to move a whole branch\nto a newer \"base\" commit.  This is done by git-rebase.  You specify\nthe branch to move (default HEAD) and where to move it to (no default),\nand git cherry-picks every patch out of that branch, applies it on top\nof the target, and moves the refs/heads/<branch> pointer to the newly\ncreated commits.\n\nBy default, \"the branch\" is every commit back to the last common\nancestor of the branch head and the target, but you can override that\nwith command-line arguments.\n\nIf you want to avoid merge conflicts due to the master code changing out\nfrom under your edits, but not have \"cleanup\" merges in your history,\ngit-rebase is the tool to use.\n\nGit-rebase will also use git-rerere if enabled (\"mkdir .git/rr-cache\").\n\n\nIf rebasing encounters a conflict it can't resolve, it will stop halfway\nand ask you to resolve the problem by hand.  However, it still knows it\nhas a job to finish!  The unapplied patches are remembered until you do\none of\n\n\tgit-rebase --continue\n\t\tThis will check in the current index.  You should\n\t\tdo git-update-index <files> in the conflicts that\n\t\tyou resolve, but NOT do an actual git-commit.\n\t\tgit-rebase --continue will do the commit.\n\tgit-rebase --skip\n\t\tThis will skip the conflicting patch.  You\n\t\tdon't have to resolve the conflicts; git will\n\t\tjust back up and try the next patch in the series.\n\tgit-rebase --abort\n\t\tThis will abandon the whole rebase operation (including\n\t\tany half-done work) and return you to where you began.\n\n\n* Rebasing 2: splitting a branch\n\nGit-rebase can also help you divide up work.  Suppose you've mixed up\ndevelopment of two features in the current HEAD, a branch called \"dev\".\nYou want to divide them up into \"dev1\" and \"dev2\".  Assuming that HEAD\nis a branch off master, then you can either look through\n\n\tgit log master..HEAD\nor just get a raw list of the commits with\n\tgit rev-list master..HEAD\n\nDrawing a picture, suppose we start with:\n\no--o--o--o--o <-- master\n    \\\n     x--y--y--x--x--y <-- dev\n\nAnd want to end up with\n              x--x--x <-- dev1\n             /\no--o--o--o--o <-- master\n             \\\n\t      y--y <-- dev2\n\nEither way, you'll have to manually figure out a list of vommits that\nyou want in dev1 and create that branch:\n\n\tgit checkout -b dev1 master\n\tfor i in `cat commit_list`; do\n\t\tgit-cherry-pick $i\n\tdone\n\nYou can use the other half of the list you edited to generate the dev2\nbranch, but if you're not sure if you forgot something, or just don't\nfeel like doing that manual work, then you can use git-rebase to do it\nfor you...\n\n\tgit checkout -b dev2 dev\t# Create dev2 branch\n\tgit-rebase --onto master dev1\t# Subtract dev1 and rebase\n\nThis will find all patches that are in dev and not in dev1,\napply them on top of master, and call the result dev2.\n\nThat is, after you've manually picked out the dev1 branch commits:\n\n              x--x--x <-- dev1\n             /\no--o--o--o--o <-- master\n    \\\n     x--y--y--x--x--y <-- dev, dev2\n\nthis will automatically produce:\n\n              x--x--x <-- dev1\n             /\no--o--o--o--o <-- master\n   |         \\\n   |          y--y <-- dev2\n    \\\n     x--y--y--x--x--y <-- dev\n\nIf you had omitted the \"--onto master\" part, it would have produced instead\n\t              y--y <-- dev2\n\t             /\n              x--x--x <-- dev1\n             /\no--o--o--o--o <-- master\n    \\\n     x--y--y--x--x--y <-- dev\n\ngit-rebase abandons the original branch, since (think about it!) it never\nloses a significant change.  In the example here, the branch is\nstill accessible via the \"dev\" name, but if you had skipped creating\na \"dev2\" branch and just called it \"dev\", that branch would be gone.\n\n\n* Cherry picking and rebasing: Merging changes\n\nSuppose that you accidentally ommitted a broken source tree,\nand forgot to use \"git-commit --amend\" when comitting the following\none-liner.  Or say you didn't notice the brokenness immediately\nand made the fix a few commits later.  But now you want to\nrewrite history with the fix merged into the original commit.\n\nHere's a simple way to do it, assuming that you're fixing the\n\"dev\" branch, and the commits to merge are <commit1> and <commit2>:\n\n       1--o--o--2--o--o <-- dev\n      /\n--o--o\n\n\tgit status\t# Make sure there's no uncommitted work\n\tgit checkout -b temp <commit1>\n\tgit cherry-pick -n <commit2>\n\tgit commit --amend -a\n\n       1--o--o--2--o--o <-- dev\n      /\n--o--o\n      \\\n       1+2 <-- temp\n\nNow, we can git-rebase the remainder.  The only complication is\nthat git can't tell that the change from commit2 has been applied,\nsince the combined 1+2 change isn't \"the same\".  One option is to\ntrust that there will be amerge conflict when you try and just do:\n\n\tgit checkout dev\n\tgit rebase --onto temp <commit1>\n\t# Which will stop with a conflict\n\tgit rebase --skip\n\tgit branch -d temp\n\nThe other is to explicitly do the two stretches separately:\n\n\tgit checkout -b temp2 <commit2>^\n\tgit rebase --onto temp <commit1>\n\tgit checkout dev\n\tgit rebase --onto temp <commit2>\n\tgit branch -d temp2\n\tgit branch -d temp\n\n\n[TODO: are there any better tools for reordering patches?  Maybe explain\nhow to create an mbox file and mess with it?]\n\n\n* Dirty tricks: evil merges (advanced)\n\nGenerally, a merge is supposed to include all the changes made on\nboth contributing branches, and that's all.  But sometimes, people\nslip additional changes in.  This is known as an \"evil merge\", because\nit can be very misleading to someone reading the history.\n\nBut occasionally there are good reasons to do that.  For example, look\nat the output of \"git show v1.0.0\" in the git repository itself.\n\n(Recall that git-show uses \"git diff --cc\", which only shows\nhunks that are not trivially taken from one parent or the other.\nAny line that starts with \"++\" is not taken from either parent.)\n\nYou'll see that, as the merge was the last thing required for a 1.0.0\nrelease, the git maintainer also bumped the version number and updated\nthe changelog.  It could have been a separate commit, but didn't seem\nworth it.\n\nThis was done by forcing the git-pull to not commit:\n\n\tgit pull --no-commit . <branch>\n\t(edit as desired)\n\tgit commit\n\nThe commit message should be edited to explain that this is not just\na normal merge, as was done in this case.\n\n\n\n* Experimenting with git\n\nThe best way to learn how git works is to try it.  Once you understand\nthe basic concept well enough to not delete anything by accident, it's\nquite hard to hurt anything.\n\n\n* Experimenting with fetching\n\nRemember that fetching from a repository on the same machine is both\npossible and fast.  So if you want to play around, just make a new\ndirectory, run git-init-db, and give it a try.  You can't hurt the source\nrepoistory, and deleting the destination is as easy as \"rm -rf\".\n\n(Of course, you can hurt things with \"rm -rf\", so make certain you're\nin the right directory before excecuting that!)\n\n* Experimenting with merging\n\nTo play with non-trivial merging, get an existing git repository of\na non-trivial project (git itself and the Linux kernel are readily\navailable.  Fire up gitk to look at history, find some interesting-looking\nmerges, and redo them yourself on a test branch.\n\nAs long as you do everything on test branches, you aren't going to screw\nanything up.  So play!\n\nYou can use gitk to search for \"Conflicts:\" in the commit comments to\nfind merges that didn't go smoothly and see what happens.  (Or you can\nsearch in \"git log\" output.  gitk just draws prettier pictures.)\n\nYou can also set up two repositories on the same machine and try pulling\nand pushing between them.\n\nTo identify arbitrary commits, the 40-byte raw hex ID is probably easiest;\nyou can cut-and-paste them from the gitk window.\n\nFor example, in the git repository,\n3f69d405d749742945afd462bff6541604ecd420\n\nlooks like an interesting merge.  Its parents are\nParent: 7d55561986ffe94ca7ca22dc0a6846f698893226\nParent: 097dc3d8c32f4b85bf9701d5e1de98999ac25c1c\n\nLet's try doing that manually:\n\n$ git checkout -b test 7d55561986ffe94ca7ca22dc0a6846f698893226\n$ git pull . 097dc3d8c32f4b85bf9701d5e1de98999ac25c1c\nerror: no such remote ref refs/heads/097dc3d8c32f4b85bf9701d5e1de98999ac25c1c\nFetch failure: .\n\nCool!  I didn't know that wasn't allowed.  (I'll have to ask why it's\nnot; perhaps it's because it uses the branch name in the automatic\ncommit message.)  I could do it by hand with git-merge, but I'll just\ngive it a branch name:\n\n$ git branch test2 097dc3d8c32f4b85bf9701d5e1de98999ac25c1c\n$ git pull . test2\nMerging HEAD with 097dc3d8c32f4b85bf9701d5e1de98999ac25c1c\nMerging:\n7d55561986ffe94ca7ca22dc0a6846f698893226 Merge branch 'jc/dirwalk-n-cache-tree' into jc/cache-tree\n097dc3d8c32f4b85bf9701d5e1de98999ac25c1c Remove \"tree->entries\" tree-entry list from tree parser\nfound 2 common ancestor(s):\nd9b814cc97f16daac06566a5340121c446136d22 Add builtin \"git rm\" command\n288c0384505e6c25cc1a162242919a0485d50a74 Merge branch 'js/fetchconfig'\n  Merging:\n  d9b814cc97f16daac06566a5340121c446136d22 Add builtin \"git rm\" command\n  288c0384505e6c25cc1a162242919a0485d50a74 Merge branch 'js/fetchconfig'\n  found 1 common ancestor(s):\n  63dffdf03da65ddf1a02c3215ad15ba109189d42 Remove old \"git-grep.sh\" remnants\n  Auto-merging Makefile\nmerge: warning: conflicts during merge\n  CONFLICT (content): Merge conflict in Makefile\n  Auto-merging builtin.h\nmerge: warning: conflicts during merge\n  CONFLICT (content): Merge conflict in builtin.h\n  Auto-merging cache.h\n  Removing check-ref-format.c\n  Auto-merging git.c\nmerge: warning: conflicts during merge\n  CONFLICT (content): Merge conflict in git.c\n  Auto-merging read-cache.c\n  Auto-merging update-index.c\nmerge: warning: conflicts during merge\n  CONFLICT (content): Merge conflict in update-index.c\nRenaming apply.c => builtin-apply.c\nAuto-merging builtin-apply.c\nRenaming read-tree.c => builtin-read-tree.c\nAuto-merging builtin-read-tree.c\nAuto-merging .gitignore\nAuto-merging Makefile\nmerge: warning: conflicts during merge\nCONFLICT (content): Merge conflict in Makefile\nAuto-merging builtin.h\nmerge: warning: conflicts during merge\nCONFLICT (content): Merge conflict in builtin.h\nAuto-merging cache.h\nAuto-merging fsck-objects.c\nRemoving git-format-patch.sh\nAuto-merging git.c\nmerge: warning: conflicts during merge\nCONFLICT (content): Merge conflict in git.c\nAuto-merging update-index.c\nAutomatic merge failed; fix conflicts and then commit the result.\n\n$ git status\nHey, look, lots of interesting stuff.  Particularly, see\n# Changed but not updated:\n#   (use git-update-index to mark for commit)\n#\n#       unmerged: Makefile\n#       modified: Makefile\n#       unmerged: builtin.h\n#       modified: builtin.h\n#       unmerged: git.c\n#       modified: git.c\n\nThe \"unmerged\" (a.k.a. \"staged\") files are ones that need manual resolution.\n\n(Notice the complaint about update-index.c, which doesn't\n(I notice that update-index.c isn't listed, despite being mentioned\nas a conflict in the message.  Can someone explain that?)\n\nFixing those is easy, but as you can see from the original commit comment\nand diffs, there were some additional changes that were necessary to\nmake that compile.\n\nYou can test before committing the change, or do it the git way - commit\nanyway, then test and \"git commit --amend\" with the fixes, of any.\n\nUnlike a centralized VCS, committing is not the same as pushing upstream.\nYou can use test branches in the repository to save as much work as\nyou like.  While it's still nice to keep the public repository clean,\nyou don't have to worry about \"breaking the tree\" every time you commit.\nYou can do all kinds of stuff in test branches, and clean it up later.\n\nThis is why all the git merge tools do the commit without waiting for\nyou to test it.  The merge is usually okay, and it saves time.  If not,\n"},{"id":"297605","messageId":"7vr6vvu4km.fsf@assigned-by-dhcp.cox.net","threadId":"43371","inReplyTo":"20061120235136.4841.qmail@science.horizon.com","subject":"[Patch to DRAFT 2 (1/2)] Branching and merging with git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-22T11:02:49Z","receivedAt":"2006-11-22T11:02:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This installment is ispell only.\n\n--- a/doc\n+++ b/doc\n@@ -81,7 +81,7 @@\n * A brief digression on command names\n \n All git commands can be invoked as \"git-foo\" and \"git foo\".  This document\n-uses them interchangably.  But you have to ask for the \"git-foo\" man page.\n+uses them interchangeably.  But you have to ask for the \"git-foo\" man page.\n Git provides a few other ways to get the man page as well:\n \tman git-foo\n \tgit help foo\n@@ -120,13 +120,13 @@\n \n Since the wrapper was developed, some simple commands have been made\n \"builtin\", so for example, \"git diff\" is done internally.  There's a\n-git-diff link to retain compatability.\n+git-diff link to retain compatibility.\n \n \n * Git's representation of history\n \n As you recall from Git 101 (or the git(7) man page), git's largest\n-data strucure is the object database, holding exactly four kidnds\n+data structure is the object database, holding exactly four kinds\n of objects.  Each of them has a globally unique 40-character hex name\n (a.k.a. object IDs) made by hashing its type and contents.  Since this is\n an (effectively unforgeable) cryptographic hash, the name of an object\n@@ -141,11 +141,11 @@\n Tree objects record directory contents; they contain file names,\n permissions, and the associated tree or blob object names.\n \n-Tag objects are shareable pointers to other objects; they're generally\n+Tag objects are sharable pointers to other objects; they're generally\n used to store a digital signature, and generally point to commits.\n (Although you can tag any object, including another tag.)\n \n-Finaly, there are commit objects.  Every commit points to (contains the\n+Finally, there are commit objects.  Every commit points to (contains the\n name of) an associated tree object which records the state of the source\n code at the time of the commit, and some descriptive data (time, author,\n committer, commit comment) about the commit.\n@@ -172,7 +172,7 @@\n common, but git allows many more.  There's a limit of sixteen in\n the source code, and the most anyone's ever used in real life is 12,\n which was generally regarded as overdoing it.  The famous \"dodecapus\"\n-is commit 9fdb62af in the linux kernel repository.\n+is commit 9fdb62af in the Linux kernel repository.\n \n \n Finally, there are references, stored in the .git/refs directory.\n@@ -184,7 +184,7 @@\n - Tags are references that are intended to be immutable.\n   A tag like \"v1.2\" is a historical record.  Tag references may or may not\n   point to tag objects!  If they do, this is called a \"heavyweight tag\";\n-  the tag can hold a digital signature and can be shared between repositores.\n+  the tag can hold a digital signature and can be shared between repositories.\n   \"Lightweight tags\" point to commits directly, and are not automatically\n   shared.\n - Heads are references that are intended to be updated.\n@@ -808,7 +808,7 @@\n it's generally easier to set up a short-cut by placing the options in\n .git/remotes/<name>.\n \n-The syntax is explained in the git-fetch man page.  When this is st\n+The syntax is explained in the git-fetch man page.  When this is set\n up, \"git fetch <name>\" will retrieve all the branches listed in the\n .git/remotes/<name> file.  The ability to fetch multiple branches at\n once (such as release, beta, and development) is an advantage of using\n@@ -838,7 +838,7 @@\n If you want to watch a project that's hosted on a git server, the easiest\n way is to use \"git clone\".\n \n-git-clone creates a new repository, sets up a remotes file to reack\n+git-clone creates a new repository, sets up a remotes file to track\n every branch in the remote repository, and fetches all those branches.\n By default, it maps them to local heads as follows:\n \n@@ -868,7 +868,7 @@\n \n Then the fetch will be done, but the results will be written nowhere\n but .git/FETCH_HEAD.  This is actually the earliest form of git_fetch\n-impllemented; everything else is a later addition.  It's not something\n+implemented; everything else is a later addition.  It's not something\n you'd do on purpose much, except as part of a script that uses FETCH_HEAD,\n but it's worth mentioning it in case you type it and wonder what the\n heck happened.\n@@ -920,8 +920,8 @@\n    has the same strictures and limitations.\n \n 3) The git protocol.  This is represented with a git:// URL, and talks\n-   to a dedicated git daemon (see the git-daemin man page) on the\n-   remote machine.  It uses TP port 9418 by default.  This is a smart\n+   to a dedicated git daemon (see the git-daemon man page) on the\n+   remote machine.  It uses TCP port 9418 by default.  This is a smart\n    protocol that understands the git format and does sophisticated\n    wire compression.\n \n@@ -1066,7 +1066,7 @@\n \n That does a git fetch, updating all of the listed branches as usual,\n then merges the _first_ listed branch into HEAD.  It would be more\n-cinsistent to merge all the branches, but that's almost never what\n+consistent to merge all the branches, but that's almost never what\n you want.\n \n By the way: don't blink, you might miss it!  As I mentioned, pulling is\n@@ -1125,7 +1125,7 @@\n In the completely trivial case when O, A and B are the same, then\n all three rules apply, they all produce the same obvious result.\n \n-Git automatically finds the masrge base O as the most recent\n+Git automatically finds the merge base O as the most recent\n common ancestor of the heads A and B to be merged.\n \n When doing a merge, git uses the above 2-out-of-3 merging rules\n@@ -1147,10 +1147,10 @@\n and uses the same 2-out-of-3 rules to resolve each hunk separately.\n \n Only if all three commits have differing hunks that overlap (or come\n-so glose that git can't be sure) is git unable to automatically resolve\n+so close that git can't be sure) is git unable to automatically resolve\n the problem.  This requires manual correction, as described below.\n \n-If the merge goes well, it is automatically comitted and the HEAD branch\n+If the merge goes well, it is automatically committed and the HEAD branch\n updated to point to the new commit.\n \n \n@@ -1207,7 +1207,7 @@\n \n * Octopus merge (advanced)\n \n-The first is the \"octopus\" stratgy.  This is special because it can do\n+The first is the \"octopus\" strategy.  This is special because it can do\n a three- or more-way merge.  See 5401f304 in the git repository for\n an example.  (Run gitk, double-click on the \"SHA1 ID\" box to select\n what's already there, enter \"5401f304\" instead, and click \"Goto\".)\n@@ -1641,7 +1641,7 @@\n              \\\n \t      y--y <-- dev2\n \n-Either way, you'll have to manually figure out a list of vommits that\n+Either way, you'll have to manually figure out a list of commits that\n you want in dev1 and create that branch:\n \n \tgit checkout -b dev1 master\n@@ -1695,8 +1695,8 @@\n \n * Cherry picking and rebasing: Merging changes\n \n-Suppose that you accidentally ommitted a broken source tree,\n-and forgot to use \"git-commit --amend\" when comitting the following\n+Suppose that you accidentally committed a broken source tree,\n+and forgot to use \"git-commit --amend\" when committing the following\n one-liner.  Or say you didn't notice the brokenness immediately\n and made the fix a few commits later.  But now you want to\n rewrite history with the fix merged into the original commit.\n@@ -1722,7 +1722,7 @@\n Now, we can git-rebase the remainder.  The only complication is\n that git can't tell that the change from commit2 has been applied,\n since the combined 1+2 change isn't \"the same\".  One option is to\n-trust that there will be amerge conflict when you try and just do:\n+trust that there will be a merge conflict when you try and just do:\n \n \tgit checkout dev\n \tgit rebase --onto temp <commit1>\n@@ -1786,10 +1786,10 @@\n Remember that fetching from a repository on the same machine is both\n possible and fast.  So if you want to play around, just make a new\n directory, run git-init-db, and give it a try.  You can't hurt the source\n-repoistory, and deleting the destination is as easy as \"rm -rf\".\n+repository, and deleting the destination is as easy as \"rm -rf\".\n \n (Of course, you can hurt things with \"rm -rf\", so make certain you're\n-in the right directory before excecuting that!)\n+in the right directory before executing that!)\n \n * Experimenting with merging\n \n"},{"id":"296868","messageId":"7vlkm3u4kl.fsf@assigned-by-dhcp.cox.net","threadId":"43371","inReplyTo":"20061120235136.4841.qmail@science.horizon.com","subject":"[Patch to DRAFT 2 (2/2)] Branching and merging with git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-22T11:02:50Z","receivedAt":"2006-11-22T11:02:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This comes on top of the ispell'ed one to correct technical\ndetails:\n\n* We made describe output to be a valid object name some time ago.\n\n* With recent addition to take directory names and path patterns,\n  it is not limited to \"small number of files\" case anymore.\n\n* The original about separate-remote was full of half sentences\n  so I stitched them together to make them make some sense.\n\n* Sorry, I recently applied the same \"fix\" as Cogito got quite\n  some time ago, and  both lightweight and annotated tags are\n  now followed upon a tracking fetch.\n\n* rsync has been deprecated for quite some time.\n\n* The official party line for git-native-over-ssh is host:path\n\n* Octopus should be discouraged unless talking about truly\n  trivial merges.  Explain its downside better.\n\n* Amend is a lot handier than --no-commit, as you do not have to\n  plan ahead.  We should encourage \"Pull/merge normally and if\n  the result is not what you like, amend it\" workflow.\n\n--- a/doc\n+++ b/doc\n@@ -278,11 +278,14 @@\n \n Third is git-describe.  This is something like git-name-rev, but\n backwards: it finds the closest reference that is an ancestor of the\n-specified commit.  Its output is not acceptable git input, but takes\n-the form of either\n+specified commit.  It takes the form of either\n+\n \tv1.2\t\t(tag name), or\n \tv1.2-g12345678\t(commit 12345678, whose nearest ancestor is v1.2)\n \n+and it is accepted as an input if the abbreviated object name that follows\n+\"tagname-g\" prefix is unambiguous.\n+\n git-describe's output is intended to be used as a software version\n number, something like the \"rcsid\" feature in RCS and CVS.\n By default, git-describe uses only heavyweight tags for its naming,\n@@ -345,13 +348,14 @@\n    in the working directory.  This option can be used with no <branch>\n    specified (defaults to HEAD) to undo local edits.\n \n-2) Revert changes to a small number of files.\n+2) Revert changes to the files in the working tree.\n \n \tgit checkout [<revision>] [--] <paths>\n    will copy the version of the <paths> from the index to the working\n    directory.  If a <revision> is given, the index for those paths will\n    be updated from the given revision before copying from the index to\n-   the working tree.\n+   the working tree.  <paths> can name directories, and/or contain\n+   glob patterns to revert many files.\n \n    Unlike the version with no <paths> specified, this does NOT change\n    HEAD, even if <paths> is \".\".\n@@ -782,18 +786,12 @@\n default in future), that places copies of the remote servers' heads\n under .git/refs/remotes/<server>/<branch>.\n \n-Then you can refer to\n-\n-If you use \"git-line --use-separate-remote\", it will set\n-\n-If you want to use the \"separate remotes\" tracking branch\n-There's an alternate way, using the --use-separate-remote option\n-to git-clone.  This sets up a copy of the remote server's heads\n-under .git/refs/remotes/origin/<name>.  Then you can refer to\n-\"origin/<branch>\" whenever you want.\n+If you use \"git-clone --use-separate-remote\", it sets up a copy of\n+the remote server's heads under .git/refs/remotes/origin/<name>.\n+Then you can refer to \"origin/<branch>\" whenever you want.\n \n Because the branch names are got under .git/refs/heads, the git\n-tools will not let you commit to the branch.\n+tools will not let you commit to the remote branchbranch.\n \n * Remotes files\n \n@@ -877,7 +875,7 @@\n * Remote tags\n \n When you fetch to a tracking branch, git-fetch also fetches every\n-heavyweight tag (one that involves an actual tag object) that\n+tag under .git/refs/tags/ in the remote repository that\n points to a commit reachable from the branch head and installs a\n copy locally.\n \n@@ -913,11 +911,19 @@\n \n    http clients also need some extra index information to help them\n    find which pack files they need.  git-update-server-info is the\n-   command that generates these files, but it's run automatically\n-   from git-repack, so it's not too important to know.\n+   command that generates these files, and it is important to keep\n+   them up-to-date.  A recommended practice is to have this command in\n+   .git/hooks/update so that every time you push into the repository\n+   they are automatically updated.  You can enable the hook (which\n+   is installed when the repository is initialized) with \"chmod +x\".\n+\n+   In addition to http://, https:// and ftp:// URL are allowed and\n+   handled by the same backend that uses cURL library.\n \n 2) rsync protocol.  This is basically an alternative to http, and\n-   has the same strictures and limitations.\n+   has the same strictures and limitations.  This is deprecated and\n+   its use has been discouraged for quite some time, although it still\n+   works.\n \n 3) The git protocol.  This is represented with a git:// URL, and talks\n    to a dedicated git daemon (see the git-daemon man page) on the\n@@ -929,8 +935,9 @@\n    require any special care when repacking.  git-daemon is purposefully\n    written to provide read-only service.\n \n-4) The git protocol over ssh.  This is a git+ssh:// URL; ssh:// is\n-   accepted as a synonym.  It has the same efficiency issues as\n+4) The git protocol over ssh.  This is spelled as \"host:path\" like scp\n+   command, and ssh:// URL and git+ssh:// are\n+   accepted as synonyms.  It has the same efficiency issues as\n    plain git.  If you want to limit ssh users to just the git commands\n    necessary to share work, git provides a git-shell command that can\n    be used as a very limited login shell.\n@@ -1046,7 +1053,7 @@\n \n \n Now, you can also specify a remote repository to merge from, using a\n-git://, http:// or git+ssh:// URL.  This is what Linus does all day\n+git:// or  http:// URLs or host:path syntax.  This is what Linus does all day\n long, and why the git-pull tool is optimized to allow that.  It uses\n git-fetch to fetch the remote branch without assigning it a branch name\n (as mentioned above, it gets the magic name FETCH_HEAD), and them merges\n@@ -1213,15 +1220,15 @@\n what's already there, enter \"5401f304\" instead, and click \"Goto\".)\n \n The octopus strategy is invoked automatically when you specify more\n-than one branch at a time to merge in with \"git pull\".  It can't handle\n-complicated overlaps and file renames as well as the 2-way recursive\n+than one branch at a time to merge in with \"git pull\".  It refuses to\n+handle complicated overlaps and file renames as well as the 2-way recursive\n strategy, but if you have a number of simple, independent changes that you\n want to merge together, an octopus merge is the obvious way to document\n the fact that they're truly independent.\n \n-The only downside to using an octopus to combine a number of simple\n-changes is that any merge makes git-bisect's job harder.  If you have\n-a development history like\n+A major downside to using an octopus to combine a number of \n+changes is that an octopus merge makes git-bisect's job harder.\n+If you have a development history like\n \n     /-b-\\\n    /     \\\n@@ -1234,9 +1241,15 @@\n     \\-f-/\n \n And you know that a works but g doesn't, there's no way to do a binary\n-search on b through f; they have to be searched linearly.  This is\n-no harder to bisect, and a lot nicer-looking than the equivalent with\n-2-way merges:\n+search on b through f; they have to be searched linearly.  In\n+addition, a merge tends to become more error prone as it has more\n+parents.  Your bisect could show that all of b, c, d, e, f are good\n+and the error is in a mismerge at g.  This is why the octopus strategy\n+refuses to do anything other than a very simple merge.\n+\n+Although an octopus is somewhat nicer-looking than the equivalent with\n+a series of 2-parent merges, the latter is a lot more efficient to\n+bisect:\n \n     /-b\n    /   \\\n@@ -1248,7 +1261,12 @@\n    \\         /\n     \\-f-----/\n \n-But if they were just done one after the other, you'd have\n+With this structure, if bisecting at h proves that it was Ok,\n+then you do not have to check b, c, d, g (the error must be in e, f\n+or mismerge at i or j).\n+\n+Even simpler to bisect is if they were just done one after the other.\n+In such a case, you'd have:\n \n --a--b--c--d--e--f--\n \n@@ -1410,6 +1428,9 @@\n \n In many cases, this is fine, and you can save it and complete the\n commit.  Or you can add something about the merge if it needs saying.\n+If the merge was complex, it will turn out to be useful to describe\n+how you choose to resolve conflicts, and that is the primary reason\n+the boilerplate lists conflicted files.\n \n When I'm done, if I don't need branch A any more, I can\n \n@@ -1763,11 +1784,11 @@\n the changelog.  It could have been a separate commit, but didn't seem\n worth it.\n \n-This was done by forcing the git-pull to not commit:\n+This was done by amending the merge commit.\n \n-\tgit pull --no-commit . <branch>\n+\tgit pull . <branch>\n \t(edit as desired)\n-\tgit commit\n+\tgit commit --amend -a\n \n The commit message should be edited to explain that this is not just\n a normal merge, as was done in this case.\n"},{"id":"295882","messageId":"7vy7q3snq8.fsf@assigned-by-dhcp.cox.net","threadId":"43371","inReplyTo":"7vslghftix.fsf@assigned-by-dhcp.cox.net","subject":"Re: [DRAFT] Branching and merging with git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-22T11:51:59Z","receivedAt":"2006-11-22T11:51:59Z","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> If you want an esoteric topic for an introductory documentation,\n> it would be more useful to talk about evil merges (an evil merge\n> is a merge commit whose result does not match any of its\n> parents).  A good example is found in\n>\n> \tgit show v1.0.0\n\nI actually remembered a better one.\n\n        Subject: Necessity of \"evil\" merge and topic branches\n        Date: Wed, 17 May 2006 23:25:55 -0700\n        Message-ID: <7vy7wz6e8c.fsf@assigned-by-dhcp.cox.net>\n\nThis talks about a real-world evil merge and the reason why it\nwas necessary, and speculates a possible way to make life\neasier.  I actually later used the \"third branch to remember the\nevil merge between two topics\" technique I talked about in the\nmessage to merge in another pair of topics, and it turned out\nthat it worked rather well.\n\nThere were two logically independent topics:\n\n - lt/setup.  Two commits, changing the calling convention of\n   setup_git_directory() function -- the final tip of the topic\n   was at a633fca0.\n\n - js/mv.  Three commits, making git-mv a built-in after\n   refactoring some code from other parts of the system -- the\n   final tip of the topic was at ac64a722).\n\nThey were not \"obviously correct\" when they started, so a topic\nbranch was used for each.  They had textually and semantically\nsome conflicts, and if they were to progress at different paces,\nthere was a need for an evil merge when the later one is merged\nto master.\n\nSo I created another branch to merge the two topics together and\nresolved their conflicts while my reading of their code were\nstill fresh.\n\n\tgit checkout -b __/setup-n-mv js/mv\n        git pull . lt/setup\n\tgit checkout next\n        git pull . __/setup-n-mv\n\nLater js/mv became ready to be merged first.  So I merged it to\n'master'.\n\n\tgit checkout master\n        git pull . js/mv\n\nI was planning to cook lt/setup a bit longer but eventually\ndecided to merge it to 'master' as well after a short while.\n\n\tgit checkout master\n        git pull . __/setup-n-mv\n\nI could have pulled lt/setup into master but then I would have\nhad to resolve the conflict between the two branches.  Since I\nrecorded the resolution earlier by making the merge, and pulled\nthat branch (which contained all of lt/setup already) into\n'master', I did not have to remember what I need to adjust when\nI did so.  If lt/setup had further updates on its own after the\n\"third branch __/setup-n-mv\" was made, I would have then pulled\nthe tip of lt/setup into 'master' to complete the merge, and\nthat would have also resulted in non-conflicting simple merge.\n\nThis would have worked equally well if lt/setup were to graduate\nfirst.\n\nThis might look too complex at the first look, but I thought it\nmight be an interesting topic in the \"hints for managing your\ntopic branches\" section.\n"},{"id":"294528","messageId":"45645243.4030400@lsrfire.ath.cx","threadId":"43371","inReplyTo":"7vlkm3u4kl.fsf@assigned-by-dhcp.cox.net","subject":"Re: [Patch to DRAFT 2 (2/2)] Branching and merging with git","fromName":"Rene Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2006-11-22T13:36:03Z","receivedAt":"2006-11-22T13:36:03Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Junio C Hamano schrieb:\n> -tools will not let you commit to the branch.\n> +tools will not let you commit to the remote branchbranch.\n\ns/branchbranch/branch/\n\n"},{"id":"296012","messageId":"20061204011958.GB28043@fieldses.org","threadId":"43371","inReplyTo":"20061120235136.4841.qmail@science.horizon.com","subject":"Re: [DRAFT 2] Branching and merging with git","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2006-12-04T01:19:58Z","receivedAt":"2006-12-04T01:19:58Z","isPatch":false,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Mon, Nov 20, 2006 at 06:51:36PM -0500, linux@horizon.com wrote:\n> I tried to incorporate all the suggestions.  There are still a few things\n> I have to research, and now I'm worried it's getting too long.  Sigh.\n\nIf you made another pass for it asking whether each sentence was really\nabsolutely necessary you'd be able to cut quite a bit without\ncompromising on content.  One example:\n\n> In CVS, branches are difficult and awkward to use, and generally\n> considered an advanced technique.  Many people use CVS for a long time\n> without departing from the trunk.\n\nLots of people have CVS experience, but not everyone does, and this\nparagraph isn't really necessary.  Cut it out, and the following\nparagraph (minus first sentence) stands just fine on its own:\n\n> Git is very different.  Branching and merging are central to effective use\n> of git, and if you aren't comfortable with them, you won't be comfortable\n> with git.  In particular, they are required to share work with other\n> people.\n\nNote also \"if you aren't comfortable with them...\" just repeats\nsomething you've already said.  So now we're down to just:\n\n\t\"Branching and merging are central to effective use of git.  In\n\tparticular, they are required to share work with other people.\"\n\nwhich is short and to the point.  Neat!\n\nI'm not sure of the ordering.  For example:\n\n> The only things that are a bit confusing are some of the names.\n> In particular, at least when beginning:\n> - You create new branches with \"git checkout -b\".\n>   \"git branch\" should only be used to list and delete branches.\n> - You share work with \"git fetch\" and \"git push\".  These are opposites.\n> - You merge with \"git pull\", not \"git merge\".  \"git pull\" can also do a\n>   \"git fetch\", but that's optional.  What's not optional is the merge.\n>\n> Also, a good habit it to never commit directly to your main \"master\"\n> branch.  Do all work in temporary \"topic\" branches, and then merge them\n> into the master.  Most experienced users don't bother to be quite this\n> purist, but you should err on the side of using separate topic branches,\n> so it's excellent practice.\n\nWe're diving in here without explaining what checkout, fetch, push,\npull, or merge are yet, or what the master branch is.\n\nThe document seems to be targetted at someone who has read some\nscattered git documentation, gotten confused, and needs help putting it\nall together.  This is understandable--there are a lot of people like\nthat right now!  But if we're going to get the documentation in some\nsort of sensible order then we need to think about how to start with\nsomeone who is a blank slate and lead them step by step to what they\nmost need to know.\n\nThat doesn't mean *you* need to do everything from scratch, but it would\nbe helpful to figure out where this would fit in with the other\ndocumentation in a logical progression.  As a start, the first paragraph\ncould say \"before reading this, we assume you've read X, Y, and Z\", and\nthen the rest of the document could be audited to make sure that it\ndidn't assume anything that isn't in X, Y, and Z.\n\n"},{"id":"295316","messageId":"20061204072350.GC28043@fieldses.org","threadId":"43371","inReplyTo":"20061204011958.GB28043@fieldses.org","subject":"Re: [DRAFT 2] Branching and merging with git","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2006-12-04T07:23:50Z","receivedAt":"2006-12-04T07:23:50Z","isPatch":false,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Sun, Dec 03, 2006 at 08:19:58PM -0500, J. Bruce Fields wrote:\n> That doesn't mean *you* need to do everything from scratch, but it would\n> be helpful to figure out where this would fit in with the other\n> documentation in a logical progression.  As a start, the first paragraph\n> could say \"before reading this, we assume you've read X, Y, and Z\", and\n> then the rest of the document could be audited to make sure that it\n> didn't assume anything that isn't in X, Y, and Z.\n\nBy the way, I have some draft rough work on getting that introductory\ndocumentation organized at\n\n\tgit://linux-nfs.org/~bfields/git.git\n\nSee Documentation/user-manual.txt and Documentation/quick-start.txt.  I\nthink I've stolen a small amount of text from you--hope that's OK!\n\nI have two ideas in mind:\n\n\t- The tutorial is supposed to a very quick \"look what git can\n\t  do\" document, but people also want it to really explain git,\n\t  prepare people to read the man pages, etc., which will make it\n\t  much longer over time.  So I'm trying to split out an\n\t  extremely concise \"quick-start\" guide (modelled partly on\n\t  Mercurial's) that doesn't even pretend to explain anything, and\n\t  a \"user manual\" that's much more verbose and tries to cover\n\t  the basics comprehensively.\n\n\t- A lot of people don't actually need to do commits or merges at\n\t  all--they just need to know how to clone a repository, check\n\t  out a few versions, etc.  (Witness the number of web pages\n\t  with \"how to check out our latest code from CVS\" out\n\t  there....) I'm also assuming most people are joining an\n\t  ongoing project instead of creating a new one.  So instead of\n\t  starting right away with init-db/add/commit, I'm putting off\n\t  actual \"development\" stuff till pretty late:\n\n\t  \t1. clone\n\t\t2. checking out old versions, basic branch management\n\t\t3. keeping up-to-date with fetch\n\t\t4. bisect\n\t\t5. archaeology (commits DAG, git-log, ...)\n\t\t6. creating commits, index file\n\t\t7. resolving merges, pull\n\t\t8. publishing a public repository, push\n\n\t  etc.  I'm hoping you'd be interested in working together on\n\t  the last parts (7 and 8 especially).\n\nComments welcomed...\n\n"},{"id":"297179","messageId":"Pine.LNX.4.63.0612041153330.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43371","inReplyTo":"20061204072350.GC28043@fieldses.org","subject":"Re: [DRAFT 2] Branching and merging with git","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-04T10:56:32Z","receivedAt":"2006-12-04T10:56:32Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 4 Dec 2006, J. Bruce Fields wrote:\n\n> So I'm trying to split out an extremely concise \"quick-start\" guide \n> (modelled partly on Mercurial's) that doesn't even pretend to explain \n> anything,\n\nyou might want to look at the QuickStart page in Git's wiki...\n\n> \t  \t1. clone\n> \t\t2. checking out old versions, basic branch management\n> \t\t3. keeping up-to-date with fetch\n> \t\t4. bisect\n> \t\t5. archaeology (commits DAG, git-log, ...)\n> \t\t6. creating commits, index file\n> \t\t7. resolving merges, pull\n> \t\t8. publishing a public repository, push\n\nAnother approach would be to illustrate short stories of a failed merge, \nor \"how I put up a public repository\", etc. Like, more example-based (and \nof course short enough that people actually read through it).\n\nCiao,\nDscho\n"},{"id":"298662","messageId":"elv4f5$kcj$1@sea.gmane.org","threadId":"43371","inReplyTo":"20061120235136.4841.qmail@science.horizon.com","subject":"Re: [DRAFT 2] Branching and merging with git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-15T21:38:05Z","receivedAt":"2006-12-15T21:38:05Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"linux@horizon.com wrote:\n\n> I tried to incorporate all the suggestions.  There are still a few things\n> I have to research, and now I'm worried it's getting too long.  Sigh.\n\nTutorials can (and usually are) be long, don't worry.\n \n\nCould you resend this as patch creating Documentation/tutorial-3.txt\nThis way it would be in the repository, and people would be able to correct\nthis (I guess that it at first would appear in 'next' branch)...\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"298192","messageId":"20061215214156.GK30858@fieldses.org","threadId":"43371","inReplyTo":"elv4f5$kcj$1@sea.gmane.org","subject":"Re: [DRAFT 2] Branching and merging with git","fromName":"J. Bruce Fields","fromEmail":"bfields@fieldses.org","sentAt":"2006-12-15T21:41:56Z","receivedAt":"2006-12-15T21:41:56Z","isPatch":false,"sender":{"key":"bfields@citi.umich.edu","avatar":null},"body":"On Fri, Dec 15, 2006 at 10:38:05PM +0100, Jakub Narebski wrote:\n> linux@horizon.com wrote:\n> \n> > I tried to incorporate all the suggestions.  There are still a few things\n> > I have to research, and now I'm worried it's getting too long.  Sigh.\n> \n> Tutorials can (and usually are) be long, don't worry.\n>  \n> \n> Could you resend this as patch creating Documentation/tutorial-3.txt\n> This way it would be in the repository, and people would be able to correct\n> this (I guess that it at first would appear in 'next' branch)...\n\nYes please.  Even if it has some problems or isn't really a perfect fit\nin the current tutorial sequence, we can fix that later.\n\n"}]}