# Version Control

> If you know the basics of git, please feel free to skip this chapter. This is for only those who do not know git.

Version control systems are used to keep track of the code changes being done. They can be used in any place which requires to keep track of changes, this book is written in markdown, using git to store tracking information and it is uploaded on github.

We will be using `git` in this chapter, the concepts are same for other version control systems, just the syntaxes might differ.

## Using git

### Init

We call each project a repository. We first need to initialize a git repository.

```
[Tasks] git init
```

This command will create an empty git repository in the current folder you are in. Ideally, this is the root folder of your project, unless your requirement is different.

```
[Tasks] vi main.go
```

### Stage changes

Create an empty file and write something into it.

```
[Tasks] git add main.go
```

Add the file to the git repo, so git knows that it should track it.

We can stage as many files we want, in this step, but the recommended things is to stage and commit one change at a time. Suppose I add a new feature of notifications, I'll make only those changes and commit all the files related **only** to that change. Because, in future if we want to rollback to the original repo, we'd rollback to the previous commit. As a consequence to this usage, we have an awful number of commits to the repo, but that's fine, since it doesn't matter. Better software managment is what matters.

When we add files to the git repo, the file is _staged_.

### Commit

```
[Tasks] git commit -m "Added initial version of main.go"
```

When we `commit`, we tell git to `finalize` the changes, it creates a unique hash to point to this time i.e. the files which we changed. Commit messages should be short and meaningful.

### Checkout

```
[Tasks] git checkout main.go
```

This unstages all the changes made to this file before the last commit. Use this with caution because it'll remove all the file changes.

### Log

```
[Tasks] git log
```

This prints a log of all commits made to the repo.

### Diff

```
[Tasks] git diff
[Tasks] git diff <commit hash>
```

diff will show the changes made to the file as compared to the file's contents of the last commit.

## Branching

While working on a team project, we are using the same codebase (on the server) with local repos on our individual machines. Adding a new feature to the `master` branch is a bad way of writing code, because if our change fails and we push the changes to the remote server, we make the server's version fail as well. This is why, branching is a good way to write code.

1. Create a new branch per feature.
2. Make changes to the branch.
3. Submit a pull request.
4. Merge the branch only if everything works fine.

By default the branch is master.

```
[Tasks] git branch new-feature
```

Creates a new branch.

```
[Tasks] git branch
* master
  new-feature
```

The branch in use is still the master.

```
[Tasks] git checkout new-feature
```

Now the branch being used is the new-feature.

Going forwards, all the changes would be made to the new-feature repository.

## Remote

```
[Tasks] git remote add origin https://github.com/thewhitetulip/Tasks

[Tasks] git remote -v
origin  https://github.com/thewhitetulip/Tasks (fetch)
origin  https://github.com/thewhitetulip/Tasks (push)
```

### Push and Pull

If you want to push your changes to the remote server, do a

```
[Tasks] git push origin master
```

`Origin` is the remote repo and `master` is the branch name which you want to push the commits to.

This book isn't about git, there already is an [amazing book](https://git-scm.com/book/en/v2) on git.

### Gitignore

At times in a project we want a few files to be not tracked, such files are placed in the `.gitignore` file in the root of the git repository. Any file or file pattern which is present in `.gitignore` is ignored by Git.

## Links

-[Previous section](9.0unittesting) -[Next section](9.2socketprogramming)
