Hello, guys! Welcome to my lovely, sincere blog.
I experienced something very annoying with Git a month ago, and it made me learn Git in more detail.
Guess what happened.
I literally threw ALL MY WORK away because of a small mistake or, rather, because of my lack of knowledge.
Luckily, it didn’t cost me too much since it was not a huge project. But for this reason, HERE WE GO! This blog post is for everyone, especially me, to reinforce our knowledge of Git.
Getting Started with Git
Git is a version control system. Basically, it is a tool that records versions of your code over time, allowing you to return to previous versions.
GitHub, on the other hand, is a platform that hosts Git repositories online. Basically, it helps you collaborate with other developers and keep a remote copy of your project.
You can think of a typical Git workflow as having four zones.
Stage Meaning What Moves It Here Working directory The project files you are currently working on Editing the files Staging area (index) The “include these changes in the next commit” listgit add
Repository (.git)
Locally recorded commits and project history
git commit
Remote
A repository hosted elsewhere, such as on GitHub
git push
Creating a New Repository
First, create a directory for your project and enter it:
mkdir my-project
cd my-project
Enter fullscreen mode Exit fullscreen mode
Then initialize a Git repository:
git init -b main
Enter fullscreen mode Exit fullscreen mode
The git init command creates a hidden .git directory inside your project. This contains commits, branch references, and other information that Git needs to track the project.
Here, -b main sets the initial branch name to main.
Cloning an Existing Repository
If the project already exists on GitHub, you don’t need to create a new repository again. Instead, you can clone it:
git clone https://github.com/username/project.git
Enter fullscreen mode Exit fullscreen mode
Saving Your Changes
1. Check What Changed
After editing your files, check the current state of your repository:
git status
git diff
Enter fullscreen mode Exit fullscreen mode
git diff shows changes to tracked files that have not been staged yet.
2. Add Changes to the Staging Area
To add changes from a specific file to the staging area:
git add <file-path>
Enter fullscreen mode Exit fullscreen mode
To stage all changes under the current directory, excluding untracked files that are ignored:
git add .
Enter fullscreen mode Exit fullscreen mode
You can also examine the changes in the staging area before committing:
git diff --staged
Enter fullscreen mode Exit fullscreen mode
3. Create a Commit
After adding changes to the staging area, let’s create a commit:
git commit -m "your commit message"
Enter fullscreen mode Exit fullscreen mode
You can think of a commit as a snapshot of your project based on what is in the staging area.
Your commit message should be short but meaningful, so you can use a pattern such as <type>(<scope>): <short explanation>.
feat
feat(auth): add password reset flow
Adding a new feature
fix
fix(cart): prevent negative quantity
Fixing a bug
refactor
refactor(api): split user service into modules
Restructuring code without changing its behavior
chore
chore(deps): bump eslint to v9
Maintenance work, such as dependency updates
docs
docs(readme): update install instructions
Documentation change
Working with Branches
Branches are like pointers. Each branch points to a specific commit in your project’s history. As you create new commits on that branch, the pointer automatically moves forward to the latest commit.
The commands below assume that the repository has a remote called origin and that main tracks its remote counterpart, as it normally does after cloning.
1. Update the Main Branch
If we are working on a project hosted on GitHub, we should switch to main and get the latest changes.
git switch main
git pull --ff-only
Enter fullscreen mode Exit fullscreen mode
--ff-only allows the update only if Git can move the branch forward without creating a merge commit. If the local and remote histories have diverged, the update stops.
2. Create a New Branch
To create a new branch and switch to it at the same time, you can use:
git switch -c feature/login-page
Enter fullscreen mode Exit fullscreen mode
Once you are on the new branch, you can check, stage, and commit your changes using the commands we covered earlier.
3. Push the Branch to GitHub
git push -u origin feature/login-page
Enter fullscreen mode Exit fullscreen mode
Using -u on the first push sets up a tracking relationship between the local branch and the remote branch. On subsequent pushes, you can just use git push.
4. Merge Branches
git switch <target-branch>
git merge <source-branch>
Enter fullscreen mode Exit fullscreen mode
First, switch to the branch that will receive the changes. Then merge the source branch into it. The source branch is not deleted by this operation.
The merge takes place locally. To update the target branch on the remote:
git push
Enter fullscreen mode Exit fullscreen mode
You do not have to push the source branch before merging it locally. You can merge it into the target branch and then push only the updated target branch.
Alternative: Merge with a Pull Request
Instead of merging locally with git merge, you can push the branch to GitHub and open a pull request. This allows others to review and discuss the changes before they are merged.
A pull request is not a Git command; it is a feature provided by GitHub and other hosting platforms.
Resolving Merge Conflicts
I am sure you have experienced merge conflicts before and paused for a second in confusion.
The good news is that this is totally normal. You need to decide which code will remain, which code will go, or how to combine the two versions.
When there is a conflict during a merge, you may see a code block like the one below:
<<<<<<< HEAD
code from your current branch
=======
code from the branch you are merging
>>>>>>> feature-branch
Enter fullscreen mode Exit fullscreen mode
- Open the conflicted file and find the marker lines.
- Edit the code into the final version you want to keep.
- Delete all the marker lines.
- Run
git add <file-path>for each resolved file. - Once all conflicts are resolved, run
git committo complete the merge.
Setting Work Aside and Undoing Changes
Switching Tasks with Git Stash
The question is: Is it possible to switch branches while there are changes that have not been committed yet?
Yes, of course! Switching branches is sometimes possible without stashing, but Git may stop you if the switch would overwrite your changes. Git stash is useful when you want to set your unfinished work aside temporarily.
Imagine that you need to switch to main immediately while you are working on the login page.
git status
git stash push -u -m "unfinished login form"
git switch main
Enter fullscreen mode Exit fullscreen mode
The -u option also includes untracked files, but not ignored files.
When you are ready to continue working on the login page:
git switch feature/login-page
git stash pop
Enter fullscreen mode Exit fullscreen mode
git stash pop reapplies the most recent stash to your current branch and removes it from the stash list if it is applied successfully. If conflicts occur, the stash is kept.
Reset, Restore, and Revert
When I was new to GitHub Desktop, I was randomly right clicking different options and found the “Revert Changes in Commit” option.
I simply thought that it would delete my changes and leave nothing behind.
ACTUALLY, IT KEEPS THE COMMIT HISTORY.
There are many undo commands. Yeah, the idea is the same, to undo something, but they operate on different targets.
commit1 → commit2[mistake] → commit3 → commit4[you are here]
Enter fullscreen mode Exit fullscreen mode
1. git revert <hash>
Revert does not delete that commit. Instead, it creates a new commit that undoes the changes introduced by it.
2. git reset <hash>
Reset moves the current branch back to the selected commit. If you reset to commit2, commit3 and commit4 are no longer part of that branch’s history, but they are not necessarily deleted immediately.
Also, resetting to commit2 keeps the mistake introduced in commit2. To go back to before that mistake, you would reset to commit1.
In the commands below, replace commit2 with its actual commit hash.
-
git reset --soft commit2→ The branch moves back, but the staging area and working files stay unchanged. The changes aftercommit2remain staged. -
git reset --mixed commit2→ This is the default mode. The staging area is reset, but working files stay unchanged. The changes aftercommit2remain unstaged. -
git reset --hard commit2→ The staging area and tracked working files are reset tocommit2, discarding local changes. It can also overwrite untracked files that are in the way.
Be careful with --hard. Previously committed work may still be recoverable through reflog, but uncommitted changes may be lost.
3. git restore <file>
This does not change the commit history. By default, it restores a file in the working directory from the staging area, discarding unstaged changes in that file.
To unstage a file while keeping its changes in the working directory:
git restore --staged file.txt
Enter fullscreen mode Exit fullscreen mode
Happy Coding, Safe Committing!
So, that’s it!
I’m still learning, but now those commands feel a little less scary. Hopefully, this post made them less scary for you too.
And a little reminder from me to you and especially to myself: check what you’re doing before running a command you don’t fully understand. Your future self will thank you.
Thanks for spending some time on my lovely little blog. See you in the next post; hopefully without losing any work this time 🙂