--- title: "Introduction to git" draft: false date: 2019-10-22T19:00:00+02:00 image: "uploads/Git-Logo-2Color.png" tags: [GIT, training, tutorial] categories: [Projects, English] --- As you man now I work in a research lab. Nearly everyone in our lab needs to do at least some programming. There are trained software engineers next to people how write their first line of code here. As we produce a lot of code that is only scripts not many people used git or any other version control system. For all the good reasons (some are mentioned in the guide) we everybody to learn git in a way that is tradeoff between good version control and fast development. As most of us work on separate projects there is not so much need to collaborate which is reflected ind this guide as I completely excluded branching and merge conflicts. Yet I hope this will maybe help some learners of git or some people that need to introduce git to others. I will not be updating this guide, for the newest version please visit https://github.com/GerJuli/introduction-to-git Now enjoy the guide! # Installation * On Windows: Download git here: https://git-scm.com/download/win and install it * On Linux: execute 'sudo apt install git' in the terminal # Configuration ## Basics ```bash $ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com ``` Run these commands without --global to apply changes only for local repository. ## Advanced * Change from default editor by executing `$ git config --global core.editor vim` * Create aliases by: - `git config --global alias.unstage 'reset HEAD --'`: Introduces new command unstage - `git config --global alias.hist 'log --pretty=format:"%h - %an, %ar : %s" --graph'`: Is an pretty alternative to git log. * Check the configuration by `$ git config --list` # Getting started ## Create an directory Select an directory of your choice e.g. ~/Desktop/git-training/, open the terminal there and type ```bash $ git init ``` Congratulations you have your first git repository! ## Committing files Create some text files e.g. `hallo.txt` or `hello_world.py`. To start version-controlling them add the file to git by using the command ```bash $ git add filename ``` You can also add multiple files. E.g. you want to add all text files the do ```bash $ git add *.txt ``` Now we can commit these changes by typing ```bash $ git commit ``` This will open your preferred text editor where you can type in a commit message. ### Commit messages *Commit messages are important* Why are the so important? Because it is much easier to track bugs with it, they describe the process of development, make it easier for others to work with your code (e.g. code review) and will help you in two years to understand what you did. They extend your labbook in its function. #### How to write commit messages * Use present tense and use imperative * Tell why you did changes. * Limit yourself to 50 characters in the first line. * Wrap the body at 72 characters #### Good commit messages For short commits that need only few explanation it is convenient to use ```bash $ git commit -m "Fix typo in introduction to user guide" ``` For long commit message you use ```bash $ git commit ``` which opens a text editor and lets you describe your changes in detail. Do not forget the line between header and body of the commit message. ``` Summarize changes in around 50 characters or less More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of the commit and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); various tools like `log`, `shortlog` and `rebase` can get confused if you run the two together. Explain the problem that this commit is solving. Focus on why you are making this change as opposed to how (the code explains that). Are there side effects or other unintuitive consequences of this change? Here's the place to explain them. Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary here ``` #### Hall of shame Here you see some examples of bad commit messages. * “bug fix”, "more work”, “minor changes”: Bad because it contains no useful information * “Change X constant to be 10”: Bad as it does not tell why. What was changed is easy to find out by git diff. * “super long commit message goes here, something like 100 words and lots of characters woohoo!”: Bad because it is unreadable. ## Storing changes on remote server To store changes on a remote server e.g. Github you need to push your repository there. If you are doing this for the first time you first need to define where to push your repository to. Use ```bash $ git remote add origin https://github.com/GerJuli/introduction-to-git.git ``` The URL can be replaced with any URL that points to an existing repository. This can even be a USB drive! Now push by using `git push -u origin master`. With this command you created an upstream to your remote 'origin' where you branch 'master' will be pushed. As this is set up you can use `git push` from now on. # Cloning existing repositories Downloading existing repositories is called 'cloning'. You can do this by using ```bash $ git clone https://github.com/GerJuli/introduction-to-git.git ``` That is it. Now you can start working on it. # Workflow ## Check status With ```bash $ git status ``` you can check the status of your current directory. This will look like this: ```bash $ git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean ``` ## Add file If you now add a file to the repository e.g. README then the status changes. ``` bash $ echo 'My Project' > README $ git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add ..." to include in what will be committed) README nothing added to commit but untracked files present (use "git add" to track) ``` You can also run ```bash $ git diff ``` which will show you the changes that where made. Now track the file by adding it to the staging area via ``` bash $ git add README ``` If you want to commit only a part of the changes you made use ```bash git add -p ``` git will ask you for every "hunk"(part of the file) if you want to add it to the staging area. The main options are: * y stage this hunk for the next commit * n do not stage this hunk for the next commit * q quit; do not stage this hunk or any of the remaining hunks ## Committing The changes are now ready to be committed ``` bash $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README ``` Now commit this change with a suitable commit message. You forgot what you changed and `git diff` does not work? If you already added the file to the staging area you can run ```bash $ git diff --staged ``` ## Push to remote Push this now to your repository with ```bash $ git push ``` ## Show last changes ```bash $ git log ``` shows you a log of recent commit messages. If you want to have a look at the changes source use ```bash $ git log -p ``` A much prettier version is ```bash $ git log --pretty=format:"%h - %an, %ar : %s" --graph ``` # Get latest changes An amazing thing of git is to work together with others. This guide will not go into the details of this, yet you will often have to get the latest changes of a project. You can do this easily by using ```bash $ git pull ``` which is a short version of two different commands. It first executes `git fetch` that downloads the latest changes. Then it runs `git merge FETCH_HEAD` which tries to apply the newest changes to your local repository. This is also the difficulty of this as any file that was changed locally and in the remote repository will cause a *merge conflict* as git does not know which file/parts of the file to keep. The resolution of such a conflict can be complicated and goes beyond the intentions of this guide. A brief overview can be found [here](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-using-the-command-line). ## Gitignore Sometimes you do not want git to track every file in your repository. Typically this applies for log files, configuration files (where maybe passwords are stored) and compiled sources. For this purpose you can create the file `.gitignore` in your repository. This file will be read by git. An example `.gitignore` looks like this: ```gitignore # ignore all .log files *.log # ignore all files in any directory named config build/ # but do track sample.log, even though you're ignoring .log files above !sample.log # only ignore the TODO file in the current directory, not subdir/TODO /TODO # ignore all files in any directory named build build/ ``` You can generate gitignore files [here](https://www.gitignore.io/). # Undoing things ## Make changes to the last commit You forgot to add one file to your commit? You are unhappy with your commit message? Use `git --amend`! ```bash $ git commit -m 'Pretty commit message' $ git add forgotten_file $ git commit --amend ``` Do not do this if you already pushed to remote. ## Unmodifying a Modified File You made changes to a file but the changes messed everything up? You can always go back to the version of the last commit by ```bash git checkout -- filename ``` *Warning*: This is dangerous as you delete all changes that you made locally. Do NOT use this command unless you are absolutely sure what you are doing. ## Time machine Something went terribly wrong. When using git this is no problem. Just use `reflog` and select the commit where still everything was alright. ```bash $ git reflog 9bff138 HEAD@{0}: commit: Document limitations of this guide 8d9dac8 HEAD@{1}: commit (amend): Adjust script to nice print [...] 2b66f53 HEAD@{7}: commit: Introduce git log 8835c33 HEAD@{8}: commit: Fix of formating of headings 2f0f500 HEAD@{9}: commit: Improve order of comments on workflow 249dc14 HEAD@{10}: commit (amend): Explain git diff f5ba1d3 HEAD@{11}: commit: Explain git diff 0a2ce1c HEAD@{12}: commit: Remove trailing whitspaces 735511f HEAD@{13}: commit (initial): Initial commit $ git reset HEAD@{index_where_everything_was_fine} $ git reset --hard origin/master ``` *Warning*: This is dangerous as you delete all changes that you made locally. Do NOT use this command unless you are absolutely sure what you are doing. # USB sticks as remote Sometimes (e.g. you are working on a machine that is not connected to the internet) it can be helpful to use an USB drive as remote. ## How to prepare the drive Go to the USB drive ```bash $ cd /media/username/git-stick/ ``` Create a directory for your repository ```bash $ mkdir my-repo ``` Initialize the repo ```bash $ cd my-repo $ git init --bare ``` ## How to push to a USB drive To push to a USB drive you need to add a remote. Go to your local repository and use ```bash $ git remote add usb /media/username/git-stick/my-repo/ ``` Be aware that your stick will have a different name and will be at a different location, depending on your operating system. You named the remote "usb" here, of course you can change that name. Now push your repo ```bash $ git push usb ``` To list all repositories just type ```bash $ git remote origin usb ``` If you want to push to the USB drive by default you can use ```bash $ git push -u usb master Branch 'master' set up to track remote branch 'master' from 'usb' ``` # What this guide does not cover * Branching - Creating branches - Merging branches (and merge conflicts) - Remote branches - Tagging - Forks * Usage of Github * Hooks # Further reading * Official git website [Git SCM](https://git-scm.com/): Extensiv documentation * [Oh shit Git](https://ohshitgit.com/): Help when you messed up. # Logo Git Logo by Jason Long {{< chat git >}}