Working with Git and GitHub is often an essential part of your daily programming tasks. In many cases, you'll want both a local Git repository and a remote GitHub repository for a project.

What Do Git, GitHub, and Repository Mean?

A repository, or "repo" for short, stores and tracks the versions of your project files. As you make changes to those files, you commit (or copy) those files into the repository for safekeeping. The repository keeps a list of all your committed changes, called a commit history. Git is a popular and widely used version control system for creating and working with repositories. It runs locally on your computer. You can download, install, and use Git on any platform without any cost or fees. With Git, you create a local repository in your project's working folder and Git stores the commit history for the files in that folder.

Git Installation

For Git installation on Linux, macOS, and Windows, please follow the platform-specific instructions below:

Linux:

Install Git on Debian-based systems like Ubuntu:

$ sudo apt-get update $ sudo apt-get install git

macOS:

Install Git using Homebrew:

$ brew install git

Windows:

Download and install Git from git-scm.com. After installation, verify with:

$ git --version

Git Configuration

If you're new to Git, configuring your identity is an essential step. This helps Git attribute your commits correctly. Follow these steps:

  1. Open a terminal or command prompt.
  2. Set your name using the following command:
  3. $ git config --global user.name "Your Name"
  4. Set your email address using the following command:
  5. $ git config --global user.email "youremail@example.com"

These configurations are global, applying to all your Git projects. You can also set project-specific configurations by omitting the "--global" flag.

Git Init

If you have a directory (folder) and you want to use git with it. Follow these steps:

  1. Navigate to your directory.
  2. Open the terminal.
  3. Run git init and that's it.

Now, if you look back at the directory and enable hidden files to become visible (ctrl + h on linux), you'll see a folder called .git which means that this folder is now a git repository and you're ready to go!
You don't have to worry about that hidden folder. Basically, Git will use it to store information about your repo but you don't need to touch it.
If you remove it, the folder is no longer a git repo and all commits will be removed.

Git Clone

If you're new to Git and want to start working on an existing project hosted on a remote repository (e.g., GitHub), you'll need to use the "Git Clone" command. This command allows you to make a local copy of the entire project on your computer. Here's how to do it:

  1. Open a terminal or command prompt.
  2. Decide where you want to store the local copy of the project on your computer. Navigate to the directory where you want the project to be saved using the terminal. For example:
  3. $ cd /path/to/your/preferred/directory
  4. Now, you're ready to clone the project. You need to know the URL of the remote repository. If you're using GitHub, you can find it on the repository's page. Run the following command, replacing "repository-url" with the actual URL:
  5. $ git clone repository-url

Here's what each step does:

Once the cloning process is complete, you'll have a local copy of the project on your computer, and you can start working on it. You can make changes, create branches, and later use "Git Push" to send your changes back to the remote repository for collaboration with others.

Remember that "Git Clone" is typically used when you want to start working on a project that already exists. It's a great way to get involved in open-source projects, collaborate with a team, or simply work on your own projects.

Git Add

git add is one of the most important commands. Let's understand how it works.
First, let's create a new Git repo using git init command.
I'll create a new git repo called example in desktop (I'm using Linux, but Git commands should be the same on any OS):

$ mkdir example $ cd example $ git init

Now, Run:

$ git status

You should get an output similar to this:

On branch main No commits yet nothing to commit (create/copy files and use "git add" to track)

Let's create a new file called file1.txt:

$ touch file1.txt

Run in your terminal:

$ git status

You should get something like that:

On branch main No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) file1.txt nothing added to commit but untracked files present (use "git add" to track)

As you can see, we now have untracked files (well, it's actually just one file) and Git is telling us to use git add command to include an untracked file (or files) and track it.
So, let's do that:

$ git add file1.txt

Run:

$ git status

Output:

On branch main No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: file1.txt

As you can see, Git is telling us to commit changes now. But hey what did the command git add do?
Well basically, it adds the file(s) you pass to it to the Staging Area. So our file1.txt is now in the Staging Area (well actually it's a copy of the file). But what's the Staging Area?

Git uses two important areas to function:

  1. Working Directory (Also known as Working Tree).
  2. Staging Area (Also known as Index).

Working Directory is the directory your currently working on (in our case, it is example). Easy, right?

Now, let's talk about the Staging Area. You can think of it as a box.
We know that a box contains some random things like books. In Git, the box contains files. So, our box was empty. When we did:

$ git add file1.txt

We added a copy of file1.txt to the box (Staging Area). Ok got it Staging Area is a box that contains copies of files that exist in our Working Directory but what's the point of it?

Why do we store things in a box? So, we can use them later if we need to!

The same thing applies to Git! We can recover the content (or just some content) of a box and change our Working Directory when needed (For example, when we make a mistake).

We can add as many files as we want like this:

$ git add file1.txt file2.html ...

Or add them all at once:

$ git add .

Now all we need to do is to commit the box and we're done! Read the next section to learn how to do so.

Git Commit

Let's continue our Git journey using the example folder we created in Git Add section 🤠!

As we saw in Git Add section, the command git add is used to add copies of files in the Staging Area (Or a box if that makes sense to you).

Imagine that you have some books that you want to store in boxes. You have books about science, physics, math, history....

How would you store them? Well obviously, store each book according to its kind (science, math...) in a specific box

But what if we just store books randomly without organizing them and after, say, one year I want to read a specific book? Oh no, there are many boxes and you will take so long to find just that one book. However, if we, for example, put a ticket on each box and say this box is for science and this one is for math... it will be easy to find our target!

That's exactly what commmits are! Basically, tickets that hold messages so we can find our copies of files easily if we need to!

Remember that we still have a copy of file1.txt in the Staging Area that we added using git add file1.txt.
Now to finish our current box that contains this copy, we need to commit it using git commit command like so:

$ git commit -m "Create a new file"

You can replace the message "Create a new file" with any one you wish like "First commit" but it's best to choose a name depending on the changes you've made (in this case, creating a new file). It's a convention to use a verb in the present simple as the first word like I did.

-m is called a flag. If you don't specify it, Git will open an editor and you'll be able to choose the message there as well as an optional explanation to why you did these changes.

There are many flags you can use with different Git commands but for now, let's not worry about them.

Now we have a new box (More correctly, a commit) in our Git History (just like your browser's history).
Run in your terminal:

$ git log

You should get an output similar to this:

commit edee7b7362e47751f6ace4507cd2fc1686f57966 (HEAD -> main) Author: <username> <somegithub@gmail.com> Date: Thu Oct 5 22:00:16 2023 +0100 Add a new file

As you can see, this is our new created box. Date is the creation date. Author is the username and github email of the creator (I used fake ones here) that were set using git config command. Also the text edee7b7362e47751f6ace4507cd2fc16 is called a hash. It's actually what we'll be using and not the message when we want to go back to some specific commit (or a box).
NOTE: Every commit has a unique hash and that's how Git exactly differentiate between them.

Ok, Let's practice more:

  1. Write any text inside file1.txt.
  2. git add it.
  3. git commit it with a message of "Write some text" or anything.
  4. Now create two new files file2.txt and file3.txt.
  5. git add them.
  6. git commit with a message of "Create two new files" or whatever using git add file2.txt file3.txt or both at once: git add ..
  7. Now git log Git History.

As you can see, Git organizes our work and remembers changes we've made over time so we don't get lost and we can add features safely in our apps without worrying about losing current progress since we can just recover data from old commits.

Git Reset

Let's recap what we have learnt so far:

  1. git add is used to add copies of files that were recently created or edited from Working Directory to the Staging Area.
  2. git commit is used to commit (In other words, add to Git History) these changes that were added to the Staging Area.
  3. Remember: first git add and then git commit.
  4. git log lets us check Git History.

Ok. Now, let's learn a new command: git reset!

Let's create a new Git repository called foo:

$ git init foo $ cd foo

Next, create a new file called hello.txt:

$ touch hello.txt

Write in the new file (We'll make typos on purpose and let's assume we did not notice it):

Hello World! I'm a nw prgramer!

Let's add the file to the Index (Staging Area) and commit:

$ git add . $ git commit -m "Create hello.txt and write some text in it"

Now let's create a new file called bye.txt, add it, and commit the changes:

$ touch bye.txt $ git add . $ git commit -m "Create bye.txt"

So now your Git History should look like this:

commit 45cdf54583460c091faa106e201e2bc6a1ef99a6 (HEAD -> main) Author: <username> <somegithub@gmail.com> Date: Fri Oct 6 10:36:29 2023 +0100 Create bye.txt commit ffe5e5ebf54223dcea4dbe661b0256f912bd9350 Author: <username> <somegithub@gmail.com> Date: Fri Oct 6 10:31:43 2023 +0100 Create a file and write some text in it

Only at this point, we've realized that we made wrong changes in the first commit!
we realized that our hello.txt's text is not what was supposed to be!

Thankfully, Git offers commands to fix this issue. We can, for example, just edit the file and then use git add and git commit with a message of "Fix a typo" or whatever. This is the safe (and recommended) way since it doesn't delete current commits

Or we can go the unsafe way using something like git reset.

This command basically deletes as much commmits as we want! Let's try it:

  1. Run in your terminal:
  2. $ git log
  3. Now, look for the commit that holds our changes which is the first one in our case:
  4. commit ffe5e5ebf54223dcea4dbe661b0256f912bd9350 Author: <username> <somegithub@gmail.com> Date: Fri Oct 6 10:31:43 2023 +0100 Create a file and write some text in it

  5. Copy that commit's hash. Mine is: ffe5e5ebf54223dcea4dbe661b0256f912bd9350
  6. Run (replace my hash with yours):
  7. $ git reset ffe5e5ebf54223dcea4dbe661b0256f912bd9350

    Running this command will delete every commit after this one (In our case, just "Create bye.txt" commit).


Now if you run git log, you can see "Create bye.txt" commit has been deleted and our old commit is the new HEAD (Don't worry about the HEAD for now, we'll cover it in upcoming lessons).

You may have noticed that our Working Directory hasn't changed. That's because we didn't add --hard option, which tells Git to undo the changes we've made after our target commit as if we never made them in the first place. So, in this case, our command is:

$ git reset ffe5e5ebf54223dcea4dbe661b0256f912bd9350 --hard
NOTE: This command won't delete untracked files (an untracked file is a file that was never before added to the Staging Area) because Git doesn't know they exist until you git add them at least one time.

If we don't specify any option, the default is --mixed, which tells Git to keep changes but clear the Index (Staging Area). That means any file we git added will be removed from Index.

There's also --soft option, which is like --mixed but doesn't clear the Index. Usually, you would use --hard option more frequently than the other two.

Another way to use git reset is:

$ git reset HEAD~<number_of_commits_to_remove>

So, in our example, we could do:

$ git reset HEAD~1 --hard

Which does the same thing.

Another use for git reset is to remove files from the Index like:

$ git reset file1.txt file2.txt ...

Or using the "all" syntax:

$ git reset .

Remember:

BIG WARNING: Never ever git reset commits made by other developers unless you let them know you want to do so. That's because, it will cause complex merging conflicts that can be hard to solve and developers will have hard times looking at Git History since this command deletes commits and that's why it's unsafe. Instead, prefer to use git revert <hash> which is a safe way to undo changes. It achieves that by undoing them and adding a new commit without affecting any existing commits. If the commits are made by you, then it's perfectly fine to use git reset.

Git Push

After making changes to your local repository and committing them, you'll want to push those changes to a remote repository (e.g., on GitHub). This ensures that your changes are available to others. Follow these steps:

  1. Open a terminal or command prompt.
  2. Navigate to your local repository directory using the terminal.
  3. Run the following command to push your changes to the remote repository:
  4. $ git push origin branch-name

If you're not sure which branch to push, the default branch is usually named "main." You can omit the branch name, and Git will use "main" by default. This command will upload your changes to the remote repository, making them accessible to your collaborators.

Git Pull

If you're collaborating with others and they have made changes to the remote repository, you'll want to update your local repository to include those changes. Use the following steps:

  1. Open a terminal or command prompt.
  2. Navigate to your local repository directory using the terminal.
  3. Run the following command to pull changes from the remote repository:
  4. $ git pull origin branch-name

If you're not sure which branch to pull, the default branch is usually named "main." You can omit the branch name, and Git will use "main" by default. This command will fetch the latest changes from the remote repository and merge them into your local branch, ensuring your repository is up to date with the latest changes.

Here are some useful references: