summaryrefslogtreecommitdiffstats
path: root/web/input/doc/faq/git.md
blob: 23989d2bee16dc6a79a902f91dc11c34cd61a4f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
title: Git
parent: FAQ
---

# How do I use Git?

After the 1.4.13 release, the project moved to [Git][git] for its code
repositories.  This document is a quick introduction to Git.

## Basic Concepts

Git is a distributed source code management (SCM) system.  This doesn’t mean
we can’t have a central shared Git repository (and we indeed have one), this
means distributed development can occur around that central repository.

Git has an additional stage between the working directory and the repository.
The idea is that you might be working on multiple unrelated things without
wanting to commit all changes in one go.  Therefore, the changes that should
be committed must first be added to the so-called *index*, which can be seen
as a staging area of the repository.  This is usually done with **git add**,
both for new files *and* for changes to existing ones.  When you commit using
**git commit**, only the changes in the index are considered.

After committing, the changes are still local.  To share them with others, you
have to push them to a remote repository, or have someone pull from your
publicly accessible repository (in most cases you will still have to push
changes there, unless if you were running a git daemon straight off your
working repository).

Finally, you can’t miss the fact that there are no revision numbers, and the
distributed nature of Git is the reason for that: there is absolutely no way a
single number could be tracked in a distributed way.  Instead, Git uses SHA1
hashes to identify commits (as well as other objects in the repository).  Each
branch and tag refer to an object name (SHA1 hash), and each commits have one
or more parents (commit objects).  Although SHA1 hashes are 40 digits long,
with Git you only have to type a handful of digits to reference one.

## Cloning a Project

To work on a project you first have to clone it.  This creates your own local
repository, and until you want to distribute your change or merge changes from
someone else, everything that follows can happen offline.  If you have push
access to the Monitoring Plugins repository, run the command:

    $ git clone git@github.com:monitoring-plugins/monitoring-plugins.git

If you just want a local copy or wish to clone it to your workstation, you can
run this command instead:

    $ git clone git://github.com/monitoring-plugins/monitoring-plugins.git

This will create a directory called `monitoring-plugins` with all the `master`
code and history (this is roughly equivalent to CVS/SVN `HEAD`).  Change
directory to `monitoring-plugins`.

## Editing Files

You can edit the files in the working area.  To check the status, use:

    $ git status

This will show a list of changes in the working directory.  Newly made changes
appear in red, while changes added to the index are shown in green.  You can
use **git diff** to see changes between the current working directory and the
index (untracked files will not be shown).

## Committing Files

Use **git add** to specify which new files/changes you want to commit; this
will add the changes to the index.  You can select only partial diffs with
**git add -p** too.  If you want to commit everything you can use **git commit
-a** directly.  You can see the changes you are about to commit (the
difference between HEAD and the index) with **git diff --staged**, and then
commit them with:

    $ git commit

Add a comment (you *have* read the [Development Guidelines][guidelines],
right?  :-)).  This commit will be local (affecting only your own repository),
so you will have to either push your changes, or have someone pull them from
you (in the latter case you will most likely still push to a publicly
accessible clone of your local repository).  If the change is from a
contributor, set the author at commit time:

    $ git commit --author="Jane Doe <jane@example.com>"

If you realize that you forgot something in your commit and haven’t pushed it
yet to a remote repository, you can amend your last commit with **git commit
--amend**.  You can also amend after a push and force the next update, however
this will cause non-linear updates and should be done only if all developers
using your repository are aware of it.

## Reverting Local Modifications

You can revert local modifications with the following steps.  First, if you
have already staged the changes you will have to unstage them.  As indicated
in the **git status** message you can do so with the following command:

    $ git reset HEAD <file>

Then you can revert unstaged changes with:

    $ git checkout <file>

If you have already committed changes locally and need to undo your commit(s),
you can use **git reset**.  First find the commit names with **git log** and
then do either one of these: To keep local modifications (you can commit them
again, stash them, etc.)

    $ git reset --soft <commit>

Note that for the purpose of “re-doing” the last commit, **git commit
--amend** will be much easier than a reset/commit with the same end result.
To discard local modifications (if you lose important changes with this
command you may be able to recover them with **git reflog** and **git checkout
<commit\>**):

    $ git reset --hard <file>

Do not reset changes that have already been pushed to remote repositories as
this will cause non-linear updates.  If you do so, all developers using those
repositories should be aware of it.

## Merging Remote Changes

When you work on your local repository you’ll need to keep it up to date with
the development tree.  This is very similar to **svn update**, with the
difference that it can’t be done if the working tree has any unmerged changes.
If you do, either commit them or put them aside (hint: **git stash**).  If you
cloned from the main Git repository, this command will do a fetch and then
merge any new changes:

    $ git pull

You can also merge changes from any other fork of the repository.  This
usually happens if someone asks you to pull from his own repo for some fix or
enhancements.  Together with **--no-commit**, you will have a chance to review
the changes and make any relevant correction before the merge.  Example:

    $ git pull --no-commit git://example.com/path/to/repo.git master

## Merging Back to the Main Repository

Once you’re done with your commits, and after pulling from the main
repository, you can push your changes back to it.  If you cloned using the
*push* URL, this command will push the master branch:

    $ git push

It you’re trying to push something that would generate merge conflicts, the
push will be rejected.  You will have to do a pull first, fix any conflicts
locally, and then push again.  If your commits are local (you haven’t pulled
them from someone else or published them somewhere) you can rebase to avoid a
merge:

    $ git pull --rebase

Like a merge, this may generate conflicts and let you fix them, but instead of
creating a merge commit on top of the others, it will undo your commits,
fast-forward and apply your commits again.  This is cleaner, but doesn’t play
well when it rewrites already published history.

## Going Further

This is a very quick introduction to Git.  There are a lot more useful
commands for manipulating changes and working with others.  They are all very
well documented (see **git help [-a]** for a list of commands, **git help
<cmd\>** or **git <cmd\> --help** shows the man page).  You might also want to
look into some of the references listed below, or into a book such as [Scott
Chacon][scott]'s [Pro Git][book-home] (which is [freely available][book-free]
on the [Git web site][git]).

## References

-  Intro to Distributed Version Control (Illustrated)  
   <http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/>
-  A tutorial introduction to Git  
   <https://www.kernel.org/pub/software/scm/git/docs/gittutorial.html>
-  Everyday Git With 20 Commands Or So  
   <http://www.kernel.org/pub/software/scm/git/docs/everyday.html>
-  Git User’s Manual  
   <http://www.kernel.org/pub/software/scm/git/docs/user-manual.html>
-  Git QuickStart  
   <http://git.or.cz/gitwiki/QuickStart>
-  Git CheatSheet  
   <http://git.or.cz/gitwiki/GitCheatSheet>
-  Understanding Git Conceptually  
   <http://www.eecs.harvard.edu/~cduan/technical/git/>
-  The Git Parable  
   <http://tom.preston-werner.com/2009/05/19/the-git-parable.html>
-  Git for Computer Scientists  
   <http://eagain.net/articles/git-for-computer-scientists/>

[guidelines]: doc/guidelines.html "Monitoring Plugin Development Guidelines"
[git]: http://git-scm.com/ "Git"
[scott]: http://scottchacon.com/ "Scott Chacon"
[book-home]: http://www.apress.com/9781430218333 "Pro Git at Apress"
[book-free]: http://git-scm.com/book "Pro Git for Free"

<!--% # vim:set filetype=markdown textwidth=78 joinspaces expandtab: # %-->