X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=Documentation%2Ftutorial.txt;h=79884d9c74d3175e179dc5a83e9163908242d6ca;hb=0d313b2b7bb219542473a25ad042f4b990e69a45;hp=fa79b016c77a7f37ae1e289eb42bb008174eda81;hpb=cf1e6d1ec55264272be8b7f0c276a069d2aac69a;p=git.git diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index fa79b016c..79884d9c7 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -11,6 +11,18 @@ diff" with: $ man git-diff ------------------------------------------------ +It is a good idea to introduce yourself to git before doing any +operation. The easiest way to do so is: + +------------------------------------------------ +$ cat >~/.gitconfig <<\EOF +[user] + name = Your Name Comes Here + email = you@yourdomain.example.com +EOF +------------------------------------------------ + + Importing a new project ----------------------- @@ -26,12 +38,13 @@ $ git init-db Git will reply ------------------------------------------------ -defaulting to local storage area +Initialized empty Git repository in .git/ ------------------------------------------------ You've now initialized the working directory--you may notice a new directory created, named ".git". Tell git that you want it to track -every file under the current directory with +every file under the current directory with (notice the dot '.' +that means the current directory): ------------------------------------------------ $ git add . @@ -40,7 +53,7 @@ $ git add . Finally, ------------------------------------------------ -$ git commit -a +$ git commit ------------------------------------------------ will prompt you for a commit message, then record the current state @@ -52,41 +65,91 @@ Try modifying some files, then run $ git diff ------------------------------------------------ -to review your changes. When you're done, +to review your changes. When you're done, tell git that you +want the updated contents of these files in the commit and then +make a commit, like this: ------------------------------------------------ -$ git commit -a +$ git add file1 file... +$ git commit ------------------------------------------------ -will again prompt your for a message describing the change, and then -record the new versions of the modified files. +This will again prompt your for a message describing the change, and then +record the new versions of the files you listed. It is cumbersome +to list all files and you can say `git commit -a` (which stands for 'all') +instead of running `git add` beforehand. + +------------------------------------------------ +$ git commit -a +------------------------------------------------ A note on commit messages: Though not required, it's a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description. Tools that turn commits into email, for -example, use the first line on the Subject line and the rest of the +example, use the first line on the Subject: line and the rest of the commit in the body. -To add a new file, first create the file, then ------------------------------------------------- -$ git add path/to/new/file ------------------------------------------------- +Git tracks content not files +---------------------------- + +With git you have to explicitly "add" all the changed _content_ you +want to commit together. This can be done in a few different ways: + +1) By using 'git add ...' + + This can be performed multiple times before a commit. Note that this + is not only for adding new files. Even modified files must be + added to the set of changes about to be committed. The "git status" + command gives you a summary of what is included so far for the + next commit. When done you should use the 'git commit' command to + make it real. + + Note: don't forget to 'add' a file again if you modified it after the + first 'add' and before 'commit'. Otherwise only the previous added + state of that file will be committed. This is because git tracks + content, so what you're really 'add'ing to the commit is the *content* + of the file in the state it is in when you 'add' it. + +2) By using 'git commit -a' directly + + This is a quick way to automatically 'add' the content from all files + that were modified since the previous commit, and perform the actual + commit without having to separately 'add' them beforehand. This will + not add content from new files i.e. files that were never added before. + Those files still have to be added explicitly before performing a + commit. + +But here's a twist. If you do 'git commit ...' then only +the changes belonging to those explicitly specified files will be +committed, entirely bypassing the current "added" changes. Those "added" +changes will still remain available for a subsequent commit though. + +However, for normal usage you only have to remember 'git add' + 'git commit' +and/or 'git commit -a'. -then commit as usual. No special command is required when removing a -file; just remove it, then commit. + +Viewing the changelog +--------------------- At any point you can view the history of your changes using ------------------------------------------------ -$ git whatchanged +$ git log ------------------------------------------------ If you also want to see complete diffs at each step, use ------------------------------------------------ -$ git whatchanged -p +$ git log -p +------------------------------------------------ + +Often the overview of the change is useful to get a feel of +each step + +------------------------------------------------ +$ git log --stat --summary ------------------------------------------------ Managing branches @@ -141,7 +204,7 @@ $ git commit -a ------------------------------------------------ at this point the two branches have diverged, with different changes -made in each. To merge the changes made in the two branches, run +made in each. To merge the changes made in experimental into master, run ------------------------------------------------ $ git pull . experimental @@ -169,6 +232,15 @@ $ gitk will show a nice graphical representation of the resulting history. +At this point you could delete the experimental branch with + +------------------------------------------------ +$ git branch -d experimental +------------------------------------------------ + +This command ensures that the changes in the experimental branch are +already in the current branch. + If you develop on a branch crazy-idea, then regret it, you can always delete the branch with @@ -194,7 +266,7 @@ $ git clone /home/alice/project myrepo This creates a new directory "myrepo" containing a clone of Alice's repository. The clone is on an equal footing with the original -project, posessing its own copy of the original project's history. +project, possessing its own copy of the original project's history. Bob then makes some changes and commits them: @@ -209,39 +281,38 @@ at /home/bob/myrepo. She does this with: ------------------------------------------------ $ cd /home/alice/project -$ git pull /home/bob/myrepo +$ git pull /home/bob/myrepo master ------------------------------------------------ -This actually pulls changes from the branch in Bob's repository named -"master". Alice could request a different branch by adding the name -of the branch to the end of the git pull command line. +This merges the changes from Bob's "master" branch into Alice's +current branch. If Alice has made her own changes in the meantime, +then she may need to manually fix any conflicts. (Note that the +"master" argument in the above command is actually unnecessary, as it +is the default.) -This merges Bob's changes into her repository; "git whatchanged" will -now show the new commits. If Alice has made her own changes in the -meantime, then Bob's changes will be merged in, and she will need to -manually fix any conflicts. +The "pull" command thus performs two operations: it fetches changes +from a remote branch, then merges them into the current branch. -A more cautious Alice might wish to examine Bob's changes before -pulling them. She can do this by creating a temporary branch just -for the purpose of studying Bob's changes: +You can perform the first operation alone using the "git fetch" +command. For example, Alice could create a temporary branch just to +track Bob's changes, without merging them with her own, using: ------------------------------------- $ git fetch /home/bob/myrepo master:bob-incoming ------------------------------------- which fetches the changes from Bob's master branch into a new branch -named bob-incoming. (Unlike git pull, git fetch just fetches a copy -of Bob's line of development without doing any merging). Then +named bob-incoming. Then ------------------------------------- -$ git whatchanged -p master..bob-incoming +$ git log -p master..bob-incoming ------------------------------------- shows a list of all the changes that Bob made since he branched from Alice's master branch. -After examing those changes, and possibly fixing things, Alice can -pull the changes into her master branch: +After examining those changes, and possibly fixing things, Alice +could pull the changes into her master branch: ------------------------------------- $ git checkout master @@ -251,6 +322,18 @@ $ git pull . bob-incoming The last command is a pull from the "bob-incoming" branch in Alice's own repository. +Alice could also perform both steps at once with: + +------------------------------------- +$ git pull /home/bob/myrepo master:bob-incoming +------------------------------------- + +This is just like the "git pull /home/bob/myrepo master" that we saw +before, except that it also stores the unmerged changes from bob's +master branch in bob-incoming before merging them into Alice's +current branch. Note that git pull always merges into the current +branch, regardless of what else is given on the commandline. + Later, Bob can update his repo with Alice's latest changes using ------------------------------------- @@ -259,20 +342,25 @@ $ git pull Note that he doesn't need to give the path to Alice's repository; when Bob cloned Alice's repository, git stored the location of her -repository in the file .git/remotes/origin, and that location is used -as the default for pulls. - -Bob may also notice a branch in his repository that he didn't create: +repository in the repository configuration, and that location is +used for pulls: ------------------------------------- -$ git branch -* master - origin +$ git repo-config --get remote.origin.url +/home/bob/myrepo ------------------------------------- -The "origin" branch, which was created automatically by "git clone", -is a pristine copy of Alice's master branch; Bob should never commit -to it. +(The complete configuration created by git-clone is visible using +"git repo-config -l", and the gitlink:git-repo-config[1] man page +explains the meaning of each option.) + +Git also keeps a pristine copy of Alice's master branch under the +name "origin/master": + +------------------------------------- +$ git branch -r + origin/master +------------------------------------- If Bob later decides to work from a different host, he can still perform clones and pulls using the ssh protocol: @@ -288,102 +376,187 @@ Git can also be used in a CVS-like mode, with a central repository that various users push changes to; see gitlink:git-push[1] and link:cvs-migration.html[git for CVS users]. -Keeping track of history ------------------------- +Exploring history +----------------- -Git history is represented as a series of interrelated commits. The -most recent commit in the currently checked-out branch can always be -referred to as HEAD, and the "parent" of any commit can always be -referred to by appending a caret, "^", to the end of the name of the -commit. So, for example, +Git history is represented as a series of interrelated commits. We +have already seen that the git log command can list those commits. +Note that first line of each git log entry also gives a name for the +commit: ------------------------------------- -git diff HEAD^ HEAD +$ git log +commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7 +Author: Junio C Hamano +Date: Tue May 16 17:18:22 2006 -0700 + + merge-base: Clarify the comments on post processing. ------------------------------------- -shows the difference between the most-recently checked-in state of -the tree and the previous state, and +We can give this name to git show to see the details about this +commit. ------------------------------------- -git diff HEAD^^ HEAD^ +$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7 ------------------------------------- -shows the difference between that previous state and the state two -commits ago. Also, HEAD~5 can be used as a shorthand for HEAD{caret}{caret}{caret}{caret}{caret}, -and more generally HEAD~n can refer to the nth previous commit. -Commits representing merges have more than one parent, and you can -specify which parent to follow in that case; see -gitlink:git-rev-parse[1]. +But there are other ways to refer to commits. You can use any initial +part of the name that is long enough to uniquely identify the commit: + +------------------------------------- +$ git show c82a22c39c # the first few characters of the name are + # usually enough +$ git show HEAD # the tip of the current branch +$ git show experimental # the tip of the "experimental" branch +------------------------------------- -The name of a branch can also be used to refer to the most recent -commit on that branch; so you can also say things like +Every commit usually has one "parent" commit +which points to the previous state of the project: ------------------------------------- -git diff HEAD experimental +$ git show HEAD^ # to see the parent of HEAD +$ git show HEAD^^ # to see the grandparent of HEAD +$ git show HEAD~4 # to see the great-great grandparent of HEAD ------------------------------------- -to see the difference between the most-recently committed tree in -the current branch and the most-recently committed tree in the -experimental branch. +Note that merge commits may have more than one parent: -But you may find it more useful to see the list of commits made in -the experimental branch but not in the current branch, and +------------------------------------- +$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^) +$ git show HEAD^2 # show the second parent of HEAD +------------------------------------- + +You can also give commits names of your own; after running ------------------------------------- -git whatchanged HEAD..experimental +$ git-tag v2.5 1b2e1d63ff ------------------------------------- -will do that, just as +you can refer to 1b2e1d63ff by the name "v2.5". If you intend to +share this name with other people (for example, to identify a release +version), you should create a "tag" object, and perhaps sign it; see +gitlink:git-tag[1] for details. + +Any git command that needs to know a commit can take any of these +names. For example: ------------------------------------- -git whatchanged experimental..HEAD +$ git diff v2.5 HEAD # compare the current HEAD to v2.5 +$ git branch stable v2.5 # start a new branch named "stable" based + # at v2.5 +$ git reset --hard HEAD^ # reset your current branch and working + # directory to its state at HEAD^ ------------------------------------- -will show the list of commits made on the HEAD but not included in -experimental. +Be careful with that last command: in addition to losing any changes +in the working directory, it will also remove all later commits from +this branch. If this branch is the only branch containing those +commits, they will be lost. (Also, don't use "git reset" on a +publicly-visible branch that other developers pull from, as git will +be confused by history that disappears in this way.) -You can also give commits convenient names of your own: after running +The git grep command can search for strings in any version of your +project, so ------------------------------------- -$ git-tag v2.5 HEAD^^ +$ git grep "hello" v2.5 ------------------------------------- -you can refer to HEAD^^ by the name "v2.5". If you intend to share -this name with other people (for example, to identify a release -version), you should create a "tag" object, and perhaps sign it; see -gitlink:git-tag[1] for details. +searches for all occurrences of "hello" in v2.5. -You can revisit the old state of a tree, and make further -modifications if you wish, using git branch: the command +If you leave out the commit name, git grep will search any of the +files it manages in your current directory. So ------------------------------------- -$ git branch stable-release v2.5 +$ git grep "hello" ------------------------------------- -will create a new branch named "stable-release" starting from the -commit which you tagged with the name v2.5. +is a quick way to search just the files that are tracked by git. -You can reset the state of any branch to an earlier commit at any -time with +Many git commands also take sets of commits, which can be specified +in a number of ways. Here are some examples with git log: ------------------------------------- -$ git reset --hard v2.5 +$ git log v2.5..v2.6 # commits between v2.5 and v2.6 +$ git log v2.5.. # commits since v2.5 +$ git log --since="2 weeks ago" # commits from the last 2 weeks +$ git log v2.5.. Makefile # commits since v2.5 which modify + # Makefile ------------------------------------- -This will remove all later commits from this branch and reset the -working tree to the state it had when the given commit was made. If -this branch is the only branch containing the later commits, those -later changes will be lost. Don't use "git reset" on a -publicly-visible branch that other developers pull from, as git will -be confused by history that disappears in this way. +You can also give git log a "range" of commits where the first is not +necessarily an ancestor of the second; for example, if the tips of +the branches "stable-release" and "master" diverged from a common +commit some time ago, then + +------------------------------------- +$ git log stable..experimental +------------------------------------- + +will list commits made in the experimental branch but not in the +stable branch, while + +------------------------------------- +$ git log experimental..stable +------------------------------------- + +will show the list of commits made on the stable branch but not +the experimental branch. + +The "git log" command has a weakness: it must present commits in a +list. When the history has lines of development that diverged and +then merged back together, the order in which "git log" presents +those commits is meaningless. + +Most projects with multiple contributors (such as the linux kernel, +or git itself) have frequent merges, and gitk does a better job of +visualizing their history. For example, + +------------------------------------- +$ gitk --since="2 weeks ago" drivers/ +------------------------------------- + +allows you to browse any commits from the last 2 weeks of commits +that modified files under the "drivers" directory. (Note: you can +adjust gitk's fonts by holding down the control key while pressing +"-" or "+".) + +Finally, most commands that take filenames will optionally allow you +to precede any filename by a commit, to specify a particular version +of the file: + +------------------------------------- +$ git diff v2.5:Makefile HEAD:Makefile.in +------------------------------------- + +You can also use "git show" to see any such file: + +------------------------------------- +$ git show v2.5:Makefile +------------------------------------- Next Steps ---------- -Some good commands to explore next: +This tutorial should be enough to perform basic distributed revision +control for your projects. However, to fully understand the depth +and power of git you need to understand two simple ideas on which it +is based: + + * The object database is the rather elegant system used to + store the history of your project--files, directories, and + commits. + + * The index file is a cache of the state of a directory tree, + used to create commits, check out working directories, and + hold the various trees involved in a merge. - * gitlink:git-diff[1]: This flexible command does much more than - we've seen in the few examples above. +link:tutorial-2.html[Part two of this tutorial] explains the object +database, the index file, and a few other odds and ends that you'll +need to make the most of git. + +If you don't want to consider with that right away, a few other +digressions that may be interesting at this point are: * gitlink:git-format-patch[1], gitlink:git-am[1]: These convert series of git commits into emailed patches, and vice versa, @@ -397,8 +570,6 @@ Some good commands to explore next: smart enough to perform a close-to-optimal search even in the case of complex non-linear history with lots of merged branches. -Other good starting points include link:everyday.html[Everday GIT -with 20 Commands Or So] and link:cvs-migration.html[git for CVS -users]. Also, link:core-tutorial.html[A short git tutorial] gives an -introduction to lower-level git commands for advanced users and -developers. + * link:everyday.html[Everyday GIT with 20 Commands Or So] + + * link:cvs-migration.html[git for CVS users].