A Non-Scary Introduction to The Wondrous World of Git
Tags: git, github, tutorial, beginners
Published: 2021-03-19 00:00:00

---
title: "A Non-Scary Introduction to The Wondrous World of Git"
date: "2021-03-19"
categories: 
  - "technical"
tags:
  - "git"
  - "github"
  - "tutorial"
  - "beginners"
---

### Git commands you need to know, simply explained, with hands-on examples!
![cupofcode_blog_main_picture](https://miro.medium.com/max/1400/1*vvj_erU5iYqN3q3pxQotiw.png)

It doesn’t matter what's the programming language of your choice, nor which company you work for — you will use Git.

I volunteer in AliceCode and teach programming to teenage girls. Last month I introduced my group to Git, and after seeing them struggle, I noticed all the things a fresh beginner doesn’t understand (yet!)

In this blog post, we will learn the basic git commands and see them used ‘hands-on’. Hands-on means it involves active participation/usage and not just theory.

In contrast to other tutorials, it was important for me to show the flow of the communication with git, and how it looks when the command you thought would work - doesn't.

Here is a Table of Contents, for easy access:

[Let's Start With The Basics](#basics)
  [Hello world, this is the command-line](#cli)
  [Creating the Initial State](#initial-state)
[Story Time + Hands-on](#hands-on)

And here is the list of commands we will discuss:
```
git init
git clone
git add
git commit
git push
git branch
git checkout
git status
git log
git fetch
```
Shall we begin?

### <a name="basics"></a>Let's Start With The Basics

[**_Git_**](https://git-scm.com/) is a version control system that lets you manage and keep track of your source code history.  
**_[GitHub](https://github.com/)_** is a provider of Internet hosting for software development and version control using Git.  
You can use **Git** without **GitHub** if you have another host, but here we will use GitHub.

Git can get complicated and every command has several **_command-line_** **_flags_** and options, but today is just about the basics!

#### <a name="cli"></a>Hello world, this is the command-line

The **command-line interface** (CLI) is a program on your computer that allows you to create and delete files, run programs, and navigate through folders and files. On a Mac, it's called **Terminal**, and on Windows, it's **Command Prompt**. It is common to call it _a terminal_ no matter which operating system you're working with, and that is what I do as well.

|![cupofcode_blog_cli](https://miro.medium.com/max/875/0*zlkpMj-eTrxW31iw.png)|
|--|
|Now you know which operating system I worked on while creating this tutorial ;)|

**_Command-line flags_** are a common way to specify options for command-line programs, usually by one hyphen or a double hyphen. For example: `git commit -m "message"` -> -m is a flag indicating a commit message, and “message” is the message itself.

Things you should know about working with the terminal:

- `mkdir` creates a directory (folder)
- `cd <DIRECTORY>` enters inside the folder
- `./` is the current directory, and `../` is the parent directory, so you might see file names like this: `./file_in_current_folder.txt`
- **↑, ↓** on the keyboard will let you navigate previous commands
- The **TAB** key will auto-complete names

  
So, for example:
```
PS C:\Projects> mkdir git-hands-on
PS C:\Projects> cd gi<TAB> –becomes–> PS C:\Projects> cd git-hands-on
PS C:\Projects\git-hands-on> ↑ –becomes–> PS C:\Projects\git-hands-on> cd git-hands-on
```
I've created a realistic scenario that you will likely encounter yourself. You can learn by reading only, but I believe it’s more educational (and enjoyable!) to follow along.   
So, if you decided to get your hands dirty, follow the steps in the next section.  
 If not, you can jump to [the story](#hands-on) in the subsequent section.

#### <a name="initial-state"></a>Creating the Initial State

First, you need to install git ([here](https://www.youtube.com/watch?v=2j7fD92g-gE) is a tutorial for Windows) and sign up for [GitHub](https://github.com/).

After that, you need to create a similar project to the one in my example. In order to do so, you need to:

1. Create a new folder and name it `git-hands-on` 
2. Enter the `git-hands-on` folder and create three files: `Loris_file.txt` ,`Olivias_file.txt` , and `mutual_file.txt`
3. In GitHub, create a new repository, named \`_git-hands-on_\`.
4. Open your project folder in the terminal (open the terminal and `cd` to your project folder).
5. Follow the quick setup provided by GitHub: (Don't forget to change `<USERNAME>` to your GitHub username!)
```
git init  
git add .  
git commit -m "first commit"  
git branch -M main  
git remote add origin https://github.com/<USERNAME>/git-hands-on.git  
git push -u origin main  
```
What does this do? I’ll tell you, but each command has its own section in the blog-post, so don’t worry about it!   
Let’s start with the fact that all the git commands will start with `git`.

1. `git init` initializes git on your project. To be clear, this will happen only in the creation of the project, not in cloning! So when you work on an existing project, you won't need to do this step.
2. `git add .` adds all the files to the commit (we’ll talk more about it).
3. `git commit -m “first commit"` saves the changes **locally**, with the message “first commit”. What does _locally_ mean? That’s a good question and I will answer it during the hands-on section!
4. `git branch -M main` will create a remote branch named `main`. (What is a branch? You’ll see!)
5. `git remote add origin` connects the local directory to the remote git repository. 
6. `git push -u origin main` pushes the commit to the remote main branch.

After that, in GitHub, we’ll see this:

![cupofcode_blog_1_starting_point](https://miro.medium.com/max/875/0*QzkKXjeJUAbyoR5g.png)

Clicking on the commit _first commit_ will show us our text files: `Loris_file.txt`, `Olivias_file.txt`, and `mutual_file.txt`.

![cupofcode_blog_2_files](https://miro.medium.com/max/875/0*17pTzMaEIa-OS1gK.png)

So you already know our story revolves around Olivia and Lori. I am using one GitHub account, but I want to imitate two different women working from two different computers. To do so, I’ll create two directories (=folders) on my computer, and I’ll start every commit message with the author’s name.

![cupofcode_blog_folders](https://miro.medium.com/max/875/0*GBJYkakywjejKR1c.png)

Important note: Even though I will explain every command and response we will encounter here - I **highly** recommend that you read the full response from each command. Most of the time, the output - especially the error messages - will give you all the information you need!

Now we are ready to start! Wanna hear the story?

### <a name="hands-on"></a>Story Time!

Meet Olivia and Lori, who work on the same team.

![cupofcode_blog_git_story_intro](https://miro.medium.com/max/875/0*rQXJzplOynxFrwiT.png)

Lori and Olivia are starting to work on a project named `git-hands-on`, that has one branch — `main`.   
After cloning the project they’ll start working using different methods:   
**Lori** will work on her local `main` branch and push to remote `main` when she’s done.  
**Olivia** will create her own branch, push that branch to remote as well, and will update it instead of `main`. When she finishes — **Olivia** will push the finished code to `main`.   
**Lori** will finish sooner, which means she won’t encounter any conflicts — but **Olivia** will!

Sounds complicated?! Don’t worry, by the end of this blog-post it will seem simple!

#### Storyline

So let’s clarify what we will see today:

1. [Lori - clones the project](#clone)
2. [Olivia - creates her own branch: dev/olivia](#branch)
3. [Lori - add, commit, push changes to remote main](#add-commit-push)
4. [Olivia - pulls Lori's changes from remote main](#pull)
5. [Olivia - add, commit, push changes to remote dev/olivia](#add-commit-push-dev)
6. [Lori and Olivia update the same file](#push-same-file)
7. [Olivia - facing and fixing conflicts!](#conflicts)

Are you ready to start!?

![cupofcode_blog_you-can-do-it-meme](https://miro.medium.com/max/688/0*FL9BT2kSwu3ENttd.jpg)

### <a name="clone"></a>1\. Lori clones the project

`git clone https://github.com/<USERNAME>/REPOSITORY`

There is a project in GitHub called _git-hands-on_. Olivia and Lori need to clone it to their computers, so they can start working! Considering that there is only one branch on **remote** ( `main` ), the default is that the women will have a **local** `main` branch. 

When you clone a repository with `git clone`, it automatically creates a **remote** connection called _origin_ pointing back to the cloned repository that is in GitHub. That means that we have a remote version of main branch called `origin main`. Sometimes I will say `remote` and sometimes I will say `origin` - but I mean the same.

This step will look the same for both Olivia and Lori, so let’s see what Lori does:

![Loris Terminal](https://miro.medium.com/max/875/1*2-AbzmFYjR64zn-HX7MK0A.png)  

Notice that after cloning Lori went into the `git-hands-on` folder with the `cd .\git-hands-on\` command. With `ls` we can see the content of the directory, which in our case is the three text files.

Olivia has done the same, and now we have main in remote (in GitHub), and locally on each of the laptops.

![cupofcode_blog_git_clone](https://miro.medium.com/max/875/0*YIukd41OYEgH8d57.png)

### <a name="branch"></a>2\. Olivia - creates her own branch: dev/olivia

There are several reasons to create a new branch: Sometimes to separate by the author (as you will see in this case), and sometimes by feature. It’s also good if you want to get someone’s help: They can pull your branch, with all your changes, and run it locally on their computer.

So Olivia wants to create her own branch to work on:

![Olivias terminal](https://miro.medium.com/max/875/1*JUcQ_VjdRsdVeakhqWGcjQ.png)

What do we see here? 

1. `git branch` shows us the existing branches we have locally. So far we have only `main`. 
2. `git checkout -b dev/olivia` creates a new branch **derived** from the current branch we were on ( local `main`, in our case). When I say derived, I mean that whatever change was in local `main`— will be in our new branch as well.
3. `git branch` shows us both `main` and `dev/olivia`. 
4. `git checkout main` will change the branch we are working on to be `main` .
5. `git checkout noSuchBranch` will show an error because you are trying to switch to a branch that does not exist. To clarify, `git checkout **-b** <NAME>` to create a new branch, and `git checkout <NAME>` to switch to a branch.

Notice that the `dev/olivia` branch **exists only locally** on Olivia’s git, not in the remote.

![cupofcode_blog_git_checkout](https://miro.medium.com/max/875/0*lLj-rQ8pEgxDv6W1.png)

### <a name="add-commit-push"></a>3\. Lori - add, commit, push changes to remote main

This step is all about updating the remote `main` branch. This is a big chunk of the tutorial, and of your work with git. Usually, the cycle is: add, commit, push. `add` adds which updated will be committed, `commit` commits the changes, and `push` pushes the code. `add, commit, push` happens when we finished working on our task, tested it, and it is good to go!

#### The meaning behind the commands

It’s kind of like sending a package. You **add** the items, **commit** the package to the post office, and **push** it to the employee.

![cupofcode_blog_add_commit_push](https://miro.medium.com/max/875/0*hqA5pvhkPAaRxYR-.png)

It’s a good analogy because you can add multiple items to the same package (`git add` multiple times before `git commit` ).  
You can also deliver multiple packages in the same visit (`git commit` multiple times before `git push`).

It is recommended to add as much as you can to the same commit (within reason). No need to commit every change you make as you go. When you finish your task or reached a meaningful milestone — commit it. 

Let’s say I’ve made changes in three files: a, b and c. It doesn’t matter which of the options I choose:

![multiple vs single add](https://miro.medium.com/max/875/1*q5oPqrET8uT52hPa0BvOvA.png)

The output would look the same: I've pushed one commit with 3 files.  
Also, notice that adding multiple files in the same command is done with space: `git add a b c`.

When using single/multiple commits, however, the outputs are different:

![multiple vs single commit](https://miro.medium.com/max/875/1*pQsTCqpSvi5VuHSQFQnlLA.png)

When you commit each file individually, like in the example on the right side - you'll eventually push three different commits. Multiple commits in the git repository, for no good reason, can get quite messy.

This is also a good place to mention that commit messages are there to help you! So use them wisely and don't write meaningless messages, such as "update" (update where?!), "ifat" (which files? which feature?), etc.

![cupofcode_blog_git_meme](https://miro.medium.com/max/875/0*byjzhSUnyOzNtj7_.png)

If you try to push without committing, it’s like going to the post office to send a package - without the package. If you try committing without adding, it’s like coming to the post office with an empty box — they won’t take it.

Need to see it to believe it? Let’s see what happens when you try to push \*nothing\* or commit \*nothing\*:

```
PS C:\Projects\git-hands-on> git status
On branch main
Your branch is up to date with ‘origin/main’.

nothing to commit, working tree clean

PS C:\Projects\git-hands-on> git push
Everything up-to-date

PS C:\Projects\git-hands-on> git commit -m “empty commit”
On branch main
Your branch is up to date with ‘origin/main’.

nothing to commit, working tree clean
```  

Did you notice a command we haven't mentioned yet? `git status` !  
`git status` shows us the status of our work: Files that changed, files that were **added** to the commit, files that were **committed**, etc.

In our case, we have `nothing to commit, working tree clean` . When we _try to push_ regardless, it won't do anything because `Everything is up-to-date`.

Our _try to commit_ \*nothing\* is also blocked, due to `nothing to commit, working tree clean` .

#### Back to the story!

Lori was working on her local `main` branch and now wants to push her code to the **remote main.**

Let's look at her terminal:

![Loris terminal](https://miro.medium.com/max/1798/1*rEiJtop0OQJ7fKkvg_h4Wg.png)
![Loris terminal](https://miro.medium.com/max/1844/1*_bGKkGlBbOZqkxwTDFIWEQ.png)

**So what do we see here?**

1. `git status` is just to show that nothing happened yet.
2. changes in `Loris_file.txt`: I added _"Here is an update!"_ at the end of the file.
3. `git status` shows us there are changes that aren't staged for commit yet, which means we didn't add them with `git add` yet. We can also see here which file has changed: `modified: Loris_file.txt`
4. `git diff Loris_file.txt` shows us what exactly changed in the file.
5. `git add ./Loris_file.txt` adds the file to the commit.
6. `git status` after the add, shows us that now there are `changes to be committed`.
7. `git commit -m ...` commits the changes with the message _Lori - updated Loris\_file.txt_
8. `git push ...` pushes Lori's commit to the branch `origin main`

**This is our state after Lori's commit:**

- Olivia's Local - Olivia still has the original code in both branches: `main` and `dev/olivia`
- Lori's Local - Lori has her changes on top of the original code
- Remote - `origin main` has Lori's changes on top of the original code

![cupofcode_blog_git_push](https://miro.medium.com/max/875/0*WYHhnyGHWRnZPkn2.png)

### <a name="pull"></a>4\. Olivia - pulls Lori's changes from remote main

As we've seen in the prior section, Olivia is no longer updated on the latest changes in the code. A fun way to see that is by having both the ladies run the `git log` command. `git log` shows commits in various branches in the repository.

![Loris log](https://miro.medium.com/max/875/1*RRue4T0ui7l6nzWmfbNkeg.png) 

Let's start with Lori's terminal. We can see that her git is aware of 3 branches: origin/main, origin/HEAD and local main. To be honest, I don't know what the story is with `origin/HEAD` but it doesn't matter here. I always see it next to `origin/main` so let's ignore it for now.

We can also see that `origin/main` is up-to-date with Lori's local `main`, and that there is a total of 2 commits.

Now, let's look at Olivia's terminal:

![Olivias log](https://miro.medium.com/max/875/1*r2Dgsk48XKBQ8srwxdfVuA.png) 

Wow wow wow! Did you notice that there is only the initial commit, but it says here that local branch is up to date with the original main???

Unless Lori tells her, the only way for Olivia to know is to try pulling changes from remote. It doesn't mean that Olivia needs to try pull every five minutes. Ideally, Olivia will pull when she finishes working, just before pushing. If Olivia doesn't pull **prior** to pushing - git will block her from pushing.

Also, notice that on Olivia's terminal we see she has 4 branches, because she created her local `dev/olivia`.

How can Olivia be made aware of the change in remote?

![Olivias terminal](https://miro.medium.com/max/875/1*BUrHvZMuQZJtGlciu_G9Vg.png)

So, what do we have here?

1. `git pull` by itself didn't work, because it doesn't know where to pull from! If we were on `main` it would be obvious, because we cloned the local main from the remote main. `dev/olivia` branch was 'born' from the local main, and it doesn't have a remote yet.  
    As we can see from the terminal, we can define the remote with the command `git branch --set-upstream-to=origin/ dev/olivia` . There is also another way, as you will see next.
2. `git pull origin main` tells git where to pull from. we can also see here what changed.
3. `git log`, just to see the difference from the initial `git log`. We'll see it better in the screenshot below.

Here is Olivia's terminal after the pull:

![Olivias terminal](https://miro.medium.com/max/875/1*AO7TBvINALx6eD7XrLaj2A.png) 

`dev/olivia` is the branch we pulled into, so it's up to date with origin/main. The local main, on the other hand, is still on the initial commit.

![cupofcode_blog_pull_main](https://miro.medium.com/max/875/0*Qt8bnvWCmqpfZ-8P.png)

### <a name="add-commit-push-dev"></a>5\. Olivia - add, commit, push changes to remote dev/olivia

Now that Olivia is up to date, she keeps working on her file. After finishing, she wants to push it remotely, to have a backup. She can't just do `git push` because there is no `origin/dev/olivia`. She needs to create one!

So, how do you create a remote branch? There are two ways to do it. The first is to create an empty remote branch, and then push to it. The second way is to create a commit as usual and create the remote branch with the push - and that's what we will see below:

![Olivias terminal](https://miro.medium.com/max/875/1*nxtGnIv-_QmAXbdWai3FRw.png) 

So, what do we have here?

1. `status, add, commit ...` we know those already.
2. `git push -u origin dev/olivia` the -u flag is for _upstream_ and it's only needed in the first push of that new branch.

![git push -u](https://miro.medium.com/proxy/1*Nhz5Uo8tFkw3kw7mLMIAtg.png)

Pop quiz! What would we see after writing `git log` in Olivia's terminal? How many commits, and where is each branch?

Let's see if you were right:

![olivias terminal](https://miro.medium.com/max/875/1*pqIIpl5TS3jMj72FrUQJmQ.png) 

Olivia was working on `dev/olivia` and pushing to its remote branch, **after pulling from origin main**.

- dev/olivia and origin/dev/olivia has 3 commits and is the most updated
- origin/main has 2 commits - the initial one and Lori's
- local main has only the initial commit

#### Fun fact: sometimes git is unexplainable

Well, I'm sure it is explainable, but I don't know why the following thing happened. The good news is - you don't need to understand **everything** in order to use git ;)

So, I wanted to update `origin/main` from the local `dev/olivia`. I thought a simple `git push origin main` will push to the remote main, but for some reason it tried pushing from main to main: `! [rejected] main -> main`.

![olivias terminal](https://miro.medium.com/max/875/1*beMQckrla_V4fmTaKpqKXw.png) 

So, what can we do if we want to update `remote main` and we can't do it through local `dev/olivia`? We can update **local** `main` and push from there:

![olivias terminal](https://miro.medium.com/max/875/1*nvAmSnIVEvyIAwMR9jCDRg.png) 

What do we see here?

1. `git checkout main` to switch to the branch main.
2. `git pull origin dev/olivia` to be up to date with the code.
3. `git push origin main` to update the remote main branch.

![cupofcode_blog_olivia_update_origin_main](https://miro.medium.com/max/875/0*gF29SJEXPCmLY_vE.png)

Now when Olivia writes `git log` we can see all the branches are up to date.

![olivias terminal](https://miro.medium.com/max/875/1*AG40DoRVM2YUN4dOb_nVrQ.png) 

### <a name="push-same-file"></a>6\. Lori and Olivia update the same file

You might have noticed that there is a file in the project named `mutual_file.txt`. In this step, **Lori** will update it and push to `origin/main`, and **Olivia** will update it and push to `origin/dev/olivia`.

Let's start with Olivia:

![olivias terminal](https://miro.medium.com/max/875/1*3JM__ojnhkihUz_dqRqazA.png)

What do we see here?

1. `git checkout dev/olivia` to switch branch.
2. `nodepad .\mutual_file.txt` opens that file in Notepad, so we can make changes and save. It's just a way to show in the terminal that Olivia made changes to the file.
3. `git add, git commit`, we are familiar with those by now.
4. `git branch --set-upstream-to=origin/dev/olivia` - Before, we were trying to push to `origin/main` from this branch, so this will set the upstream to Olivia's branch. Just to make sure we will push there.
5. Lastly, the good old familiar `git push`.

![cupofcode_blog_olivia_push_mutual_file](https://miro.medium.com/max/875/0*c2bgrdQ72JiGu7PD.png)

In the image above you can see, I added letters to the circles that represent the commits. The pink circles are Lori's commits and the green circles are Olivia's commits. Regarding the letters:  
L = an update to `Loris_file.txt`  
O = an update to `Olivias_file.txt`  
m = an update to `mutual_file.txt`  

Olivia's update was pretty simple. With Lori, things are about to get a bit tricky. Let's look at her terminal:

![Loris terminal](https://miro.medium.com/max/1802/1*R12AZmFVQ0o55SUwP4123g.png)
![Loris terminal](https://miro.medium.com/max/1848/1*s0VA9sIKHpNL_yABMc8Gww.png)

So, what do we have here?

1. `nodepad .\mutual_file.txt` to show us that Lori made changes to the file.
2. `git add, git commit`, we are familiar with those by now.
3. `git status` after each command, I highly recommend you to read the response.
4. Lastly, `git log`, just to see where we stand.

Wait a minute!! `git log` shows something weird. We know that `origin main` has been updated since that commit with `Loris_file.txt` update. We know **Olivia** pushed to `origin main` the change from her branch (_"Olivia - modified Olivia's file"_)! If **Lori** won’t pull before pushing, and be updated on the latest version - her push will get rejected!!

Here is a visualization of the problem:

![cupofcode_git_different_commits_main](https://miro.medium.com/max/875/0*kH6Fp8ResqFYSh1D.png)

This is a great time to meet the last git command for today: `git fetch`.  
**git fetch** is the command that tells your **local** git to retrieve the latest meta-data info from the original **without** doing any file transferring. It's checking to see if there are any changes available. **git pull,** on the other hand, does that **and** brings (copies) those changes from the remote repository.

Let's see what happens after Lori fetches the changes:

![Loris terminal](https://miro.medium.com/max/1806/1*s65QPTTO6o2TOWnl8v8JTA.png)
![Loris terminal](https://miro.medium.com/max/1856/1*35L5YwArVHaKFYKxCnVZ7g.png)

So, you know what I'm about to ask... What do we have here?

1. `git fetch` notifies us about the changes, in which is the branch `dev/olivia` appears ("_\* \[new branch\] dev/olivia -> origin/dev/olivia_").
2. `git log` proves that no file was updated - the local main didn't change.
3. `git pull origin main` does make a change, in a way we haven't seen before: _Merge made by the 'recursive' strategy._
4. `git log` shows us a commit that none of the ladies created: _Merge branch 'main' of https://github.com/IfatNeumann/git-hands-on._ Why did that happen? Where is Olivia's commit?

#### `Merge branch 'main'` commit

Merge branch 'main' of https://github.com/IfatNeumann/git-hands-on

Recursive merge is what happens when we **create a commit locally, before pulling changes** from `origin`.

To clarify, Lori already created a commit and did not base it on the latest version of the code. Basing your commit on the latest version of the code is done by **pulling from origin prior to committing**. It also make sense, because in order to make sure your code is good and doesn't break anything - you need to ensure it works with the rest of the project, **as it is now**.

If Lori would've tried pushing without pulling first - it would have been rejected. Pulling changes from the origin after committing changes, 'forces' git to organize the commits one after the other even though they originally had the same parent state. By parent state I mean they were both based on the same state of the code.

Let's see how it looks in the repository:

![cupofcode_blog_git_pull_origin_main2](https://miro.medium.com/max/875/0*iNzgC8RGQ7a6hRHe.png)

Now that we understand that, let's continue with Lori's terminal:

![Loris terminal](https://miro.medium.com/max/875/1*9EG9xdglkA8_ORcXALS4ew.png)

`git status` shows us that Lori's local main is ahead of `origin/main` by 2 commits. They are her original commit (of changing the mutual file) and the recursive merge commit. Let's see how `origin/main` looks in GitHub:

![cupofcode_blog_git_conflict_2](https://miro.medium.com/max/875/0*HaGgYHXRBEyqhbWk.png)

`origin/main` now has 5 commits. As you can see in the image above, if you look at the code of the two commits, Olivia's commit and the automatic recursive merge commit - you'll see they contain the same changes.

Wow, this was a long section of the story! Here is the state of the branches at this point:

- Olivia updated the mutual file and pushed the changes to her remote branch
- Lori updated the mutual file and pushed the changes to main

![cupofcode_blog_after_updating_mutual_file](https://miro.medium.com/max/875/0*MmP-FEdoH9O-MBUU.png)

### <a name="conflicts"></a>7\. Conflicts!

As you saw, both of our ladies modified the same file, and this will for sure create a conflict. It's just a matter of time.

Time is up! Let’s see it happen!

So let’s say Olivia wants to be up-to-date with the latest main version:

![Olivias terminal](https://miro.medium.com/max/875/1*qAXC0uCOSYNeO0q1xxua8Q.png)

How does a conflict look in the code? In our case, like that:

![cupofcode_blog_19_conflict](https://miro.medium.com/max/875/0*hLHcZPCyZ6-KBpwE.png)

- `<<<<<< HEAD` marks the code you had in your local repository
- `======` marks where HEAD ends and the incoming change begins
- `>>>>>>` marks the end of the incoming code

If you have multiple occurrences of conflicts in your file, you will have multiple trios of <<<,====,>>>.

When you see a conflict, you need to choose whether you want to keep the version you have, replace it with the incoming change, or keep both. If you work with [Visual Studio](https://en.wikipedia.org/wiki/Microsoft_Visual_Studio) (an integrated development environment, as seen in the screenshot), you can do it in one click, which makes life easier. In the image above, you can see the options: `Accept Current Change | Accept Incoming Change | Accept Both Changes`.

In our case, Olivia will choose to keep both.

What do you do after you decide which code to keep? Running the command `git status` gives us the answer:

![Olivias conflict](https://miro.medium.com/max/1810/1*m_1KETWiX9M0om-MgcKmIA.png)
![Olivias conflict](https://miro.medium.com/max/1818/1*xIM5Ib5RQV6PA9AwTiUoMA.png)
![Olivias conflict](https://miro.medium.com/max/1820/1*AzuqG2NxqIiv5JV-8jElgQ.png)

What do we see here?

1. According to `git status`, we need to _fix conflicts and run "git commit"_, and also that we have _Unmerged paths: and should use "git add ..."_ 
2. After the command `git add .` I got the response:  
    `Changes to be committed:   modified: mutual_file.txt      Changes not staged for commit:   (use "git add ..." to update what will be committed)   modified: mutual_file.txt`  
    I found it a bit weird, like it's saying the modified file is to be committed and also not staged for commit, so I did an additional `git add .` and `git status`. Just to be sure.
3. After the commit, I've tried pushing to main but the response was that `Everything is up to date`. So I did the trick I've done before:
4. push to `origin/dev/olivia`, switch to local main, pull the changes from remote `origin/dev/olivia`, and push to `origin/main`.

## That's it!

![cupofcode_blog_is-the-party-over_is-the-party-over](https://miro.medium.com/max/563/0*vF44v6ypkdE3aB9v.jpg)

Now you can work with git with no problem!

Today we learned a lot: command-line interface, git, GitHub, how it works, and went over the basic commands:
```
git init
git clone
git add
git commit
git push
git branch
git checkout
git status
git log
git fetch
```
We also saw the commands used in real life, and learned how to solve conflicts!

It is ok if you feel a bit overwhelmed. The wonderous world of git is a lot to take in, and mastering it requires practice!

After today, seeing that git is not as scary as it seems, you think you're ready to learn more? Because I have some very useful commands I can share with you in a future blog-post!

* * *

I hope you enjoyed reading this article and learned something new! Want to read more? Click [here](https://cupofcode.blog/tips-for-students-dr-erez-sheiner/) to see what tips Erez Sheiner, Bar Ilan University’s Outstanding Lecturer, has for students!

I would love to hear your thoughts, here are the ways to contact me:  
Facebook: [https://www.facebook.com/cupofcode.blog/](https://www.facebook.com/cupofcode.blog/)  
Instagram: [https://www.instagram.com/cupofcode.blog/](https://www.instagram.com/cupofcode.blog/)  
Email: cupofcode.blog@gmail.com

![[https://cupofcode.blog/](https://cupofcode.blog/)](https://cdn-images-1.medium.com/max/3170/0*vLdjjgtBfeBxj_f8.png)