== Cloning a git repository == What this means is that you actually download the complete code repository to your own hard drive. This is different from centralised VCS/SCMs, which only have a copy of the files you checked out. With git you get a complete copy of the complete history, locally. This is one of the reasons why git can be very quick. git clone {repository} [{local name}] The {repository} string can point at a git:// URL, http[s]:// URL or a local file URL. When the cloning is completed, you will automatically have checked out the 'master' branch. == Introducing yourself == Git should know who you are, as that will be important for the git commit logs. So please enter a directory created by ''git clone'' and do: git config user.name 'Your name' git config user.email 'my@email.com' This will only set these variables locally in this repository. I would probably recommend you to make these changes globally as well, as this can be easy to forget if your do another git clone. git config --global user.name 'Your name' git config --global user.email 'my@email.com' Some might only need to do the latter one, but some might want to use different e-mail addresses for their commits for different projects. == Other neat features to enable == === Making git colourful === This is highly recommended, as it is easier to read commit logs and patches via the git commands this way. git config --global color.branch auto git config --global color.diff auto git config --global color.log auto git config --global color.interactive auto git config --global color.status auto git config --global color.pager true Notice that we here force colours when using the pager. This might mean you need to add one more change as well: git config --global core.pager 'less -X -R -F' === Preparing for sending patches via mail === If you choose to install the git-send-email package, you can very easily submit patches via e-mail. We will go into these details later on, but some configuration should be done. git config --global sendemail.chainreplyto false git config --global sendemail.smtpserver {your SMTP server} If you're using SSL or TLS against your SMTP server, add this: git config --global sendemail.smtpencryption {tls|ssl} (choose tls or ssl) If you're authenticating against the SMTP server, you must add: git config --global sendemail.smtpuser {your-username} You can also set your password in the config, by setting sendemail.smtppass - '''but the password will be saved in clear text!''' === Configuration files === Now do this: cat ~/.gitconfig cat .git/config As you can see, the configuration files are not that hard to read. These files may be edited manually if you want to as well. == Checking the status of the project == git status This command gives you an overview over all files which have been modified and all new and unregistered files. The output of ''git status'' should be pretty obvious. == Checking your changes == git diff [{filename}] This will list all local changes which has not been committed. == Saving changes == All files new files will need to be added to an ''index'' to be prepared for a commit. Consider this as a "pre stage" which needs to be done. This is also different from other VCS/SCMs. But it has it's advantages as well. So if you add or modifies files, you need to do this to add files to the index when you want to commit your changes: git add {filename/directory} If you have a long list of files under the ''git status'' section called ''Changed but not updated:'', you can do: git add -u This adds all these files into the index. If you now try to do a ''git diff', you'll see that nothing turns up. And if you modifies one of the files and do ''git diff' again, you'll find that only your last changes is shown. This is normal behaviour. git compares to what's in saved the index and what the local file looks like. If you want to see the changes from what's in your index and the previously committed version, you'll need to do: git diff --cached Please also try: git status Notice the change of the message for the files which you have added. Now, let's commit! git commit -s Now an editor should turn up, you can enter your commit statement and exit. Notice the ''-s'' argument. That means ''sign-off'. That adds an 'Signed-off-by: ' signature at the end of the commit log. Please do it a habit to always sign-off your commits. That simply means you approve the commit. And this is especially important if you commit work for others. To change the author of some code in the commit log, you can do that via the commit as well: git commit -s --author "Authors name " This is important to remember if you apply patches from others. This way it is possible to track from whom the different code parts came from. == Look at the commit log == git log This is the most basic usage. Other nice usages is to follow a files commit log, and not the complete project's commit history: git log --follow {filename} If you also add -p, you can also see the diff. There's also a feature called ''git show''. This shows the contents of a commit or other git objects. If you just do git show it will show the last git commit. But you can give it a commit ID which you can find in the ''git log''. If you give it a branch name or a tag name, you will see the git commit of the branch point or at the commit where the tag points at. git show 684790552dde0475745015a76762ecc5a11eedab (commit ID) git show 684790552dd (partial commit ID) git show origin/allmerged (remote branch) git show v2.1.1 (tag name) == Creating patch files == When you have done some commits, you probably want to share them. Say you want to pick out the last commit. git format-patch HEAD^1 This notation might look odd. HEAD is a keyword, which means head of the commit log. It's where the last commit happened. It's because ''git format-patch'' takes ranges. This notation means, from HEAD - 1 commit and to the last commit. If you do just HEAD, the range "distance" will be 0, and no patch file will be created. It's like saying ''from A to A''. But you really want to say, from ''A to B''. To explain that, you can do: git format-patch HEAD^1..HEAD So, what happens if you change HEAD^1 to HEAD^3 ... well, you get the 3 top-most commits as patch files. ''git format-patch'' will report the file names it generates on-the-fly. ''git format-patch'' can also take commit ID's which you find in the commit log, in addition to branch names and tag names. So if you want to have all commits from OpenVPN 2.1_rc15 to OpenVPN 2.1_rc22 ... you can do: git format-patch v2.1_rc15..v2.1_rc22 You can also do this with ''git log''. == Sending patches to the OpenVPN devel-mailing list == If you have installed the git-send-email package and done the configuration steps mentioned above, sending patches to the mailing list is just as easy as creating the patch files. Please note that the ''git send-email'' command expects to get patch file(s). Just do: git send-email --to {email address} {patch files} and follow the instructions you're given. That's all. == Tags == If you wonder where 'v2.1_rc15' came from in the example above, that's a tag name. And tags can be found by doing: git tag -l A tag is just a name of a particular commit ID. Commit ID's can be tricky to remember, and then you can insert tag names which are a bit more descriptive. == Branches == Branches are almost the same as tags, but with one difference - you can commit to them. You can also quickly create your own branch to test out things, without being worried about your former commits. First, let's look at some branches: git branch This will list all your local branches. But we also have some remote branches. git branch -r Notice the difference between them, where remote branches are prefixed with ''origin/''. This is because git tracks remote branches separately from your local branches. So you can have a master branch which is different from origin/master. Another thing, to be able to do commits on remote branches, you must check them out as a local branch before you can do commit. You can also add more remote repositories, and will then have different remote names. ''origin'' is just a remote name, which is the default name for the remote where you did your initial clone. We will not dig into this here. === Checkout a branch === In OpenVPN, there's a branch called ''allmerged''. So to checkout that branch locally, we do: git checkout -b allmerged origin/allmerged That's it :) Now you can do commits to your own copy of the ''allmerged'' branch. If you find out that you want to do some experimental stuff, to see how it works out, just do: git checkout -b my_test_branch And it will create a new branch, enter it, from the latest commit where you where. You can now even commit into this branch. === Merge branches === If you find out that one branch has some stuff you want to test out with your own stuff in your own branch, it's quite easy. git merge {branch to merge into your branch} If there are some conflicts, just do a ''git diff'' to see what they are. You need to solve these issues before you then can continue. The conflict blocks are pretty visible and you will hopefully understand what to leave in the file and what to remove. When that's done, it's the same procedure as before - ''git add'' and ''git commit''. If there were no conflicts, a merge commit is done automatically for you.