Git Fundamentals
- Radek Stolarczyk
- Mar 4, 2025
- 5 min read

📦 Starting a Project with git init (and How to Push It to GitHub)
You’ve just created a project locally. Here’s how to initialize Git and push it to GitHub:
1. Initialize a Local Repo
git initThis sets up the .git in your folder.
2. Add All and Commit Your Files
git add .
git commit -m "Initial commit"3. Link It to a GitHub Repo
Go to GitHub → click “New repository”.
Then add the remote:
git remote add origin https://github.com/username/your-repo.gitPush it:
git push -u origin main"-u" sets upstream so next time you can just run git push.
🔄 Cloning an Existing Repo from GitHub
To start working on a project from GitHub:
Go to the repo on GitHub.
Click the green “Code” button → copy the HTTPS or SSH URL.
Run:
git clone https://github.com/org/project.git✅ Adding Files to a Commit
You don’t always want to commit everything. To commit only specific files:
git add path/to/file1.js path/to/file2.py
git commit -m "Fix login test and update utils"To unstage something (before committing):
git reset path/to/file.jsTo remove a file from Git and your disk:
git rm filename.txt
git commit -m "Removing file"To keep it on disk but stop tracking it:
git rm --cached filename.txt🤔 What Does It Mean to “Unstage” Something in Git?
When you "stage" a file in Git using git add, you're telling Git:
"Hey, I want this file (or these changes) to be included in the next commit."
So, unstaging a file means:
"Wait! I changed my mind. I don't want to include this file in the next commit (yet)."
✏️ Amending Commits (Fixing Message, Adding Files, Changing Author)
1. Fix the Last Commit Message:
git commit --amend -m "New message"2. Add a Missed File:
git add forgot-file.js
git commit --amend3. Change Commit Author:
git commit --amend --author="Correct Name <correct@email.com>"⚠️ You’ll need to force push if the original commit was already pushed:
git push --force🔁 Undoing Commits
Undo Last Commit (But Keep Changes):
git reset --soft HEAD~1Undo Last Commit and Changes:
git reset --hard HEAD~1Revert a Commit (Create Opposite Commit):
git revert <commit-hash> git pushThis is safer on shared branches than reset.
🚨 Undo a git push (With Caution)
Reset to Previous Commit and Force Push:
git reset --hard HEAD~1
git push --force⚠️ Only do this on feature branches, not shared main or develop.
🍒 Cherry-Picking: Grab Specific Commits from Another Branch
Cherry-picking is super useful in QA when you need a fix from main but you're testing on a feature branch.
git checkout your-feature-branch
git cherry-pick <commit-hash>If there are conflicts, resolve them, then:
git add . git cherry-pick --continue🔍 How to Find a Commit Hash
✅ Using git log
Run:
git logYou’ll see something like this:
commit 4f3c52a9b3ac17e121eed672bdbe2713d72cb8fd
Author: Your Name <you@example.com>
Date: Tue Jun 18 15:32:10 2025 +0000
Fix flaky test in login validationThat long string (4f3c52a9...) is the commit hash.
You can copy the whole hash or just the first few characters (usually 7–10 is enough for Git to recognize it uniquely in your repo).
🔧 Git Conflict Resolution (During Merge or Rebase)
When you're working on a branch and you try to merge or rebase another branch into it (e.g., main or origin/master), Git tries to automatically combine the changes. But if both branches have touched the same lines of code differently — Git can't decide what to keep.
That’s called a merge conflict.
😕 Why You Get Conflicts
Let’s say:
You're on a feature branch.
You and someone else edited the same part of a file on main.
When you run:
git rebase origin/mainGit tries to "replay" your commits on top of the latest version of main — and hits a conflict if the same lines were changed differently.
🤔 Merge vs. Rebase — What’s the Difference?
Feature | git merge | git rebase |
History shape | Adds a merge commit | Linear history |
Use case | Team collaboration | Clean personal branches |
Keeps old branch structure | ✅ Yes | ❌ Rewrites history |
Conflict resolution | Required if overlapping edits | Same — but in replay mode |
✅ Is Rebasing with origin/master OK?
Yes, it’s perfectly fine to rebase with a remote-tracking branch like origin/main or origin/master. In fact, it’s common.
But important rule:
❗ Only rebase your own local commits.Never rebase shared commits that are already pushed and used by others unless everyone knows and agrees.
So this is safe:
git fetch origin
git rebase origin/mainYou're saying: “Hey, replay my local commits on top of the latest remote main branch.”
🧨 What Happens When You Hit a Conflict?
When Git can’t resolve a change automatically, it marks the conflicting area in the file like this:
<<<<<<< HEAD
// your current branch's version
console.log("Hello from feature branch!");
=======
console.log("Hello from main branch!");
>>>>>>> origin/main🧼 Step-by-Step: Resolving a Conflict
Open the file with conflict markers (<<<<<<<, =======, >>>>>>>).
Decide what to keep:
Your version?
Theirs?
A mix?
Manually delete the markers and clean up the code.
Example result:
console.log("Hello from both branches!");Stage the resolved file:
git add filename.jsContinue the process:
If you're rebasing:
git rebase --continueIf you're merging:
git commit⚠️ Git may do this multiple times if your branch has several commits and each one causes conflicts.
🛑 If You Want to Abort
Let’s say things got messy and you want to stop the rebase:
git rebase --abortThis puts your code back to the way it was before the rebase started.
🧠 Pro Tip: Use a Merge Tool
You can use a visual merge tool to help resolve conflicts more easily.
To launch Git’s built-in mergetool (if configured):
git mergetoolOr use your editor:
VS Code detects conflicts and gives you clickable options like “Accept Current Change”, “Accept Incoming Change”, or “Accept Both”.
WebStorm, Sublime Merge, etc. also support visual merge.
💡 Tip: Preventing Frequent Conflicts
Rebase often to keep your branch up-to-date and reduce painful conflicts later:
git fetch origin
git rebase origin/mainCommunicate with your team when multiple people are working on the same files.
🧪 Testing Tip: Creating a Temporary Branch to Debug
If you need to test a risky fix without affecting the main branch:
git checkout -b debug-fixAfter you're done, just delete it:
git checkout main
git branch -D debug-fix🕵️ Bonus: Find and Explore Commits
Log with One Line per Commit:
git log --onelineBlame (See Who Last Changed a Line):
git blame filename.js🔄 Rebase vs Merge (When Cleaning Up)
To clean up messy history:
git rebase mainUse merge if you want to keep commit history visible:
git merge main🧽 Extra Cleanup: Stashing Changes
Need to switch branches but have local edits?
git stash
git checkout another-branchTo get changes back:
git stash pop🧠 Final Tips
Use .gitignore to avoid committing logs, temp files, node_modules, etc.
Use descriptive branch names: bugfix/login-error, testcase/api-retry or feature/Jira#
Alias common commands to save time. Example:
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm commit✅ Summary Cheat Sheet
Task | Command |
Init new repo | git init |
Clone repo from GitHub | git clone <url> |
Add specific files | git add file1.js file2.js |
Unstage file | git reset file.js |
Commit with message | git commit -m "Message" |
Amend commit | git commit --amend |
Change commit author | git commit --amend --author="Name <email>" |
Revert commit | git revert <hash> |
Reset last commit (keep) | git reset --soft HEAD~1 |
Reset last commit (remove) | git reset --hard HEAD~1 |
Cherry-pick commit | git cherry-pick <hash> |
Push | git push |
Force push | git push --force |
Resolve conflict | Edit → git add → git commit/rebase --continue |