Git & GitHub — Version Control from Basics to Advanced
In short: Git is a distributed version control system: every clone has the full history, so commits, branches, diffs and logs work offline and are fast;
- you sync with remotes by push/pull.
- SVN and TFVC are centralised: history lives on one server, many operations need the server, and branching is heavier.
- Git's cheap branching enables feature branches and pull-request workflows.
In short: git fetch downloads new commits and updates remote-tracking branches (origin/main) without touching your working branch — safe to run anytime.
git pull= fetch + integrate (merge by default, or rebase with--rebase/pull.rebase=true) into your current branch, which can cause conflicts.
In short: The index between your working tree and the repository.
git addputs selected changes into it andgit commitrecords exactly what is staged.- It lets you build clean, focused commits from a messy working tree (
git add -pto stage parts of a file).
In short: Run git status to see conflicted files, open each, decide the correct code between the <<<<<<<, =======, >>>>>>> markers (keep one side, both, or rewrite), remove the markers, build and test, then git add the files and git commit (or git rebase --continue).
- Use
git merge --abortto back out. - Prevent conflicts with small, frequent merges.
In short: .gitignore stops untracked files from being added (bin/obj, node_modules, secrets).
- It doesn't affect files already tracked;
- remove them from the index with
git rm --cached <file>and commit, and they will be ignored from then on (if it was a secret, rotate it — it is still in history).
In short: Merge joins histories with a merge commit, keeps the true history and never rewrites commits — safe for shared branches.
- Rebase replays your commits on top of another branch, giving a linear history but new commit ids — use it for local/private branches to update with main or clean up before a PR.
- Never rebase commits others already have.
In short: reset moves the current branch pointer back (soft keeps changes staged, mixed keeps them unstaged, hard discards them) — it rewrites history, so only for unpushed commits.
revertcreates a new commit that undoes a previous commit — the safe way to undo something already pushed to a shared branch.
In short: Describe yours concretely, e.g. "GitFlow-like: main = production, develop for integration, feature/* per story with PRs into develop, release/* cut for UAT, hotfix/* from main merged back to both" — or "trunk-based: short-lived branches merged to main daily behind feature flags, every merge deploys to dev".
- Mention branch policies (reviewers, CI checks) and how releases are tagged.
In short: A request to merge a branch, where teammates review the diff and CI validates it before merge.
- Check: does it meet the requirement, tests, edge cases and error handling, security (secrets, injection, authorization), performance (N+1, missing indexes), naming and readability, consistency with architecture, and that the PR is small and focused.
In short: Temporarily shelves uncommitted changes so you can switch context: git stash push -m "msg" (add -u for untracked files), git stash list, git stash pop (apply and drop) or git stash apply (keep in stash).
- Useful when an urgent bug arrives mid-feature.
In short: git cherry-pick <sha> applies the changes of one commit onto the current branch as a new commit.
- Typical use: bring a hotfix from main into a release branch, or rescue a commit made on the wrong branch.
- Overuse creates duplicate commits — prefer merging when you need a whole branch.
In short: HEAD points directly to a commit instead of a branch — after checking out a tag or a commit sha.
- You can look around and even commit, but new commits belong to no branch and can be garbage-collected once you switch away.
- Create a branch (
git switch -c fix-from-tag) to keep them.
In short: It binary-searches history between a known good and a known bad commit: Git checks out the midpoint, you mark it good or bad (or git bisect run <test script> does it automatically), and in log2(n) steps it names the first bad commit.
- Great for regressions in long histories.
In short: As content-addressed objects (blob = file content, tree = directory, commit = tree + parents + metadata, annotated tag) named by their SHA-1 (SHA-256 optional) hash, compressed in .git/objects and packfiles.
- Branches/tags are refs pointing at commit ids; HEAD points at a ref.
- Changing any commit changes its hash and all descendants' hashes.
In short: First rotate/revoke the secret immediately — assume it is compromised (bots scan GitHub within minutes).
- Then remove it from the code (move to Key Vault/user secrets/environment variables), and purge it from history with
git filter-repoor BFG, force-push and ask everyone to re-clone; - on GitHub contact support to clear cached views.
- Prevent it next time:
.gitignore, pre-commit secret scanning (gitleaks), GitHub push protection / secret scanning.
In short: git branch feature/x (new branch points at your commits) → git reset --hard origin/main (move main back to the remote state) → git switch feature/x and continue.
- Nothing is lost; if anything goes wrong,
git reflogshows the old position.
In short: git revert <sha> (for a merge commit git revert -m 1 <merge-sha>), push through the normal PR/pipeline so the revert is reviewed and deployed.
- Don't
reset+ force-push a shared branch — it breaks everyone's clones and the audit trail.
In short: Fetch first.
- If the branch is only yours:
git rebase origin/main, resolve conflicts commit by commit (git rebase --continue), run tests,git push --force-with-lease. - If shared:
git merge origin/mainonce and resolve in one merge commit. - Afterwards keep it short-lived and sync daily; consider splitting the work into smaller PRs behind a feature flag.
In short: The remote branch has commits you don't have, so pushing would overwrite them.
git pull --rebase(orgit pull), resolve any conflicts, test, then push.- Only force-push (
--force-with-lease) when you intentionally rewrote your own branch.