Proper use of git for beginners and beyond
Tags: git, programming
Published: 2023-04-30 17:11:17

I have noticed that many programmers neglect the rules outlined below, or don't know about them. Nevertheless, following these rules can standardize the work of both large and small teams using git, avoid problems and errors in dev branches, and on production.

![git meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6q8hkfqkgaplfa202h3w.png)

> It is important to note that I am not a git guru and don't know all the commands and features, but I hope that this article will be useful

## "We always push to master"

The first rule that needs to be followed is to separate branches for production and development. I usually use the `main` and `develop` branches. The `main` branch is usually automatically deployed with each change, while the `develop` branch is used for development but there are no errors and all the functionality is completed.

![gitflow scheme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dwc9q5ncfjrx39jixrcm.png)

As shown in the diagram, any changes to the `main` branch come only from the `develop` branch (which may be linked to some test environment), but no one works directly with the `develop` branch. Every task should start with inheriting from `develop` and creating a new branch. Any fixes should be made in a separate branch and then merged into `develop`.

In cases where a task affects a large functionality, especially if it requires the involvement of multiple developers, it is necessary to inherit from develop into a separate "EPIC" branch. They can have sequential numbers `EPIC-100`, `EPIC-101` ... or reflect the essence `EPIC-notifications`. Each developer working on this "EPIC" should inherit from it and merge their completed task directly into it.

With this hierarchy, it becomes possible to delegate tasks to developers of different levels. For example, you can allow push to `develop` only to team-leads and senior programmers. And for some tasks, you can give full control of EPICs to middle developers so that they can control the merging of tasks of juniors and be responsible for the code quality in the EPIC. This will minimize errors and distribute responsibility for the project to all developers according to their abilities. And your branch will always be yours - sudden desynchronization of the local and remote server due to unsynchronized pushes of different programmers will not happen.

## Something is wrong - we need to roll back

Sometimes one of the developers working on a project may accidentally introduce incorrect changes (due to inexperience, carelessness, or simply because his changes did not negatively affect local development). And sometimes it can be very difficult to find and fix the cause of newly appearing bugs and errors.

> Recently, I witnessed a situation where an obscure error occurred after 8 commits on top of the last correct version of the application and over 200 changed files.

In such cases, rolling back is necessary.

Suppose we need to roll back the last 2 commits, which we believe contain the error. This can be done in 2 ways:
```bash
git revert HEAD~2..HEAD
```
That creates 2 new commits that undo the changes of the previous commits. This means that the commit history remains unchanged (new commits with changes are added).

```bash
git reset --hard HEAD~2
```
That undoes the changes made in one or more commits, completely removing them from the commit history.

**!!! I strongly advise against using the second option !!!**

Firstly, it permanently deletes commits in which, in addition to the error, there may be useful code written by other developers, which may be needed to create new commits after the rollback.

Secondly, this will undoubtedly cause synchronization problems with other developers, since the commit history in the remote repository will be changed.


![Git meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kkgf14yzviq5bjjdl8sm.png)

To summarize - use `git revert`,
...or `git reset --hard`, but you must understand what you are doing.

## Proper committing and merging

Such situations should happen extremely rarely and should be minimized as much as possible.

1) To do this, you should always understand what you are pushing to the remote repository and forget about the command `git add .` forever. Instead use the UI of your IDE to add files to the commit. In VSCode and WebStorm, you can view all modified files and click `+` on those you are sure that the changes were not accidental keystrokes, but your meaningful changes.
2) The code in your branch should be committed for each small but complete change. And the commit message should contain enough information: the task number or name and a brief description of what you have done. For example, "Notifications - creating a class for connecting to websockets."
3) But in EPIC branches and other shared branches where your commit will be merged, there should be only one commit with a reference to your branch. To do this, merging into this branch should be done with the flags `--no-commit` and `--squash`.

```bash
# In a some EPIC branch:
git merge your-branch --no-commit --squash
```

This command will not immediately merge your branch, but will only apply all the changes from your branch to the shared branch. You can view them in the UI of your IDE and double-check if you are sure about each modified file in the shared branch. After that, you can commit with a description that contains the branch name and the name of the merged branch. For example, "Site-sidebar - Notifications merged."
4) After merging into the shared branch, especially into the develop branch, you should test the functionality of your feature and the areas that you think could have been affected by your code changes. If everything works correctly, you can push the shared branch with the merge commit to the remote repository.
5) Merging into develop should be done in the same way as described above. EPIC branches, verified before, can contain many commits for each completed task. Now each EPIC needs to be merged into develop with one commit. "Site-sidebar merged". After some time, when the tasks prove their worth in action, task branches can be deleted from the repository (this can be done after a certain period, for example, 1-2 months, depending on the pace of your team's work). 

> Don't forget to use "merged" word in a description to differentiate regular commits from merging

## Some Tips


![git meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zorqkupywfgtyugm1oib.png)

1) Writing Git commands with all flags and parameters can be tiresome for programmers who are not used to typing blindly with 10 fingers, especially if they have to enter them constantly.
Personally, I use OhMyZsh to simplify some commands. If you're not a Windows user, I highly recommend it. For example:

```bash
gcmsg 'first commit'
# This is the same as
# git commit -m 'first commit'

gco develop
# git checkout develop

gcb new-branch
# git checkout -b new-branch
```

2) If you use VSCode, like I do, take a look at the Git Graph extension. Typing in the console is always faster than using the mouse to navigate, but sometimes it's hard to orient yourself in the project without a good GUI.

3) Even with this work structure, problems and errors arise. And here it is extremely important to understand how it is easier for you to communicate:

- Write comments on completed tasks in your task managers with a description of the current branch state (possibly with a description of new errors and necessary scripts to run the application),
- Mark yourself in messengers about your status
- Divide your general meetups into smaller ones - for those working on a specific epic.