Git
The distributed version control system underneath everything: how commits are stored, how branches move, how work is merged or rebased, and how mistakes are undone. Interviews go deeper here than in most tool areas, because knowing the object model is what separates memorised commands from real understanding.
on this pageshowhide
guide
overview
~1 minGit is a distributed version control system built on a small idea: every commit is a complete, content-addressed snapshot, and branches, tags and `HEAD` are names that point at those snapshots. Interviewers dig further into Git than into most tools because the commands are easy to memorise and the model underneath them is not. A candidate who can say which pointer moved, which object was created and what is still reachable can reason through an unfamiliar command; one who memorised recipes stalls at the first surprise. The hub follows the life of a change. [The object model and DAG](/topics/dev-git-object-model) is the foundation everything else refers to. [Staging and commits](/topics/dev-git-staging-commits) covers how a change becomes a commit, and [branching and merging](/topics/dev-git-branching-merging) and [rebase and history rewriting](/topics/dev-git-rebase-history) cover the two ways work is combined. [Remotes and collaboration](/topics/dev-git-remotes-collaboration) is where local history meets everyone else's, and [stash, reflog and recovery](/topics/dev-git-stash-reflog-recovery) and [inspecting history](/topics/dev-git-inspecting-history) are the toolkits for undoing and investigating. Around the core sit [hooks](/topics/dev-git-hooks), [submodules, subtrees and worktrees](/topics/dev-git-submodules-worktrees), [branching workflows](/topics/dev-git-workflows) and [configuration, ignore rules and attributes](/topics/dev-git-config-attributes). Junior rounds check the daily vocabulary: what staging is for, what fetch does that pull does not, how to read a conflict. Senior rounds turn into scenarios — a bad force-push, a lost commit, a release that shipped without its hotfix — and into team-level trade-offs between workflows, merge policies and where a check belongs. Learn the object model and the three trees first. Merge, rebase, remotes and recovery all become pointer arithmetic once those are clear.
primer
### Commits are snapshots, not diffs A commit names one tree — the full state of every tracked file — plus its parents and some metadata. Diffs are computed on demand by comparing two snapshots. Keeping that straight explains why checkout is fast, why a rename is detected rather than recorded, and why "undoing a commit" can mean several different operations. ### Everything is addressed by content Blobs, trees, commits and annotated tags are stored under the hash of their contents. Change one byte anywhere and every hash above it changes, which is what makes history tamper-evident and why any edit to an old commit produces a new commit rather than a modified one. **Rewriting history** always means making new objects and moving names. ### Names are cheap pointers A branch is a ref that stores a single commit id; `HEAD` usually names a branch, and sometimes a commit directly. Creating, deleting and moving branches costs almost nothing, so most Git commands reduce to "which pointer moves, and to where". Reachability from those names decides what `git log` shows and what garbage collection may eventually delete. ### Three trees stand between you and a commit The working tree is what you edit, the **index** is the commit you are proposing, and `HEAD` is the commit you last made or checked out. `add`, `commit`, `reset`, `restore` and both forms of `diff` are each defined by which of those three they read and which they write. Interviewers treat this as the entry test for the undo questions. ### Integration is a choice about history Merging keeps what happened and records the join; rebasing replays your work so history reads as if it happened in order. Both start from the merge base. The choice is about who else already has your commits, what reviewers will read, and how much bisect and blame matter later. ### Local first, then shared An ordinary clone is a full repository. Remote-tracking refs are your last snapshot of someone else's branches, refreshed only by fetch. Anything you have not pushed is private and can be rewritten freely; anything others have fetched is a contract, and rewriting it has a cost you must name. ### Almost nothing is lost immediately Commits that no branch points at stay in the object store until garbage collection, and the reflog remembers where each ref pointed before. Uncommitted work is the real exception: a hard reset or a forced checkout can overwrite unstaged edits with no record to recover them from.
- Blob
- The object storing one file's contents, with no name or permissions. Identical content anywhere in history is stored once.
- Tree
- The object representing one directory: a list of names, modes and the hashes of the blobs and subtrees beneath it.
- Commit object
- A snapshot pointer: one root tree, zero or more parent commits, author and committer identity, timestamps and a message.
- Ref
- A human-readable name, such as a branch, tag or remote-tracking branch, that resolves to an object id.
- HEAD
- The ref that marks what is currently checked out. Normally it names a branch; when it holds a commit id directly, HEAD is detached.
- Index
- Also called the staging area: the file describing the tree the next commit will record, built up with add and reset to match a commit by reset.
- Commit DAG
- The directed acyclic graph formed by commits pointing at their parents. Ancestry, ranges and merge bases are all questions about this graph.
- Merge base
- The best common ancestor of two commits, used as the reference point for a three-way merge and for triple-dot ranges.
- Fast-forward
- Advancing a branch to a descendant commit by moving its pointer, with no merge commit, possible only when no divergence exists.
- Rebase
- Replaying a series of commits onto a new base, producing new commits with new ids and moving the branch to the last one.
- Remote-tracking ref
- A local, read-only record such as origin/main of where a remote branch pointed at the last fetch.
- Refspec
- A source-to-destination mapping that tells fetch and push which refs to transfer and which local or remote names to update.
- Reflog
- A local, per-ref journal of the values a ref has held, used to find commits that no branch still reaches.
- Packfile
- A compressed file holding many objects, often as deltas against similar objects, used for storage and network transfer.
- Submodule
- A nested repository recorded in the parent as a pinned commit id at a path, with its URL kept in .gitmodules.
- Worktree
- An additional checkout with its own working directory, index and HEAD, sharing the object store and refs of one repository.
Almost every section of the hub is a view of the same three layers: objects in the store, refs that name them, and the three trees you work in. A commit writes new objects and moves the branch `HEAD` names. A merge or rebase reads the DAG to find the merge base, writes new commits, and moves a branch. Fetch brings objects across and refreshes remote-tracking refs; push asks the other side to move its refs, and refuses by default when that would drop commits. Reset moves a branch and optionally rewrites the index and the files on disk; the reflog records the move, which is why most recovery questions end in the reflog. The surrounding sections attach to the same points: - **Hooks** run at the moments a ref is about to change or has changed — before a commit is written, before a push is sent, when a server receives one. - **Submodules** are a special tree entry that stores a commit id of another repository; **worktrees** are extra sets of the three trees over one object store. - **Workflows** are conventions about which refs exist, who moves them and whether shared ones may be rewritten. - **Configuration and attributes** decide how the working tree is converted to blobs and back, and how diff and merge treat particular paths. Plumbing commands let you look at the layers directly. Reading them once removes most of the mystery from the porcelain: ```bash git cat-file -p HEAD # tree, parents, author, committer, message git cat-file -p 'HEAD^{tree}' # names and modes pointing at blobs and subtrees git rev-parse main origin/main # two refs, two commit ids, nothing more git merge-base main origin/main # the commit both histories share git reflog -5 main # where main pointed before its last moves ``` A strong answer to almost any scenario question walks the same route: which objects exist, which refs point where before and after, and what is still reachable afterwards.
- Object Model and DAG →
Objects, refs and the DAG are the vocabulary every other section uses; answers elsewhere assume you can reason about hashes and reachability.
- Staging and Commits →
The working tree, index and HEAD, and how a change becomes a commit; the undo commands only make sense after this.
- Branching and Merging →
Branches as pointers, fast-forwards and three-way merges, and reading conflicts: the everyday half of working with others.
- Remotes and Collaboration →
Fetch, pull, push and remote-tracking refs, where local history meets a shared one and non-fast-forward rejections appear.
- Rebase and History Rewriting →
Rewriting history deliberately, and the rules for when it is safe, once merging and remotes are clear.
- Stash, Reflog, and Recovery →
The recovery toolkit that turns most 'I lost my work' scenarios into finding a commit and pointing a name at it.
Describing a commit as a diff or a list of changes: it records a full snapshot, and diffs are computed between snapshots when asked.
Treating
git pullas a download: it also merges or rebases into your current branch, which is why fetch alone is the safe way to look.Rebasing or force-pushing a branch others have already fetched, then being surprised when their next pull duplicates or resurrects commits.
Reaching for
reset --hardto undo a pushed commit on a shared branch, where a revert keeps history forward-only and avoids a forced push.Claiming
reset --harddestroys commits: they stay reachable through the reflog for a while; it is uncommitted working-tree changes that are gone.Adding a committed file to
.gitignoreand expecting Git to stop tracking it; ignore rules only affect paths that are not yet tracked.Reading
origin/mainas the live state of the server: it is a local snapshot from the last fetch, so ahead and behind counts can be stale.Using
..and...interchangeably; they select different commits ingit logand compare different trees ingit diff— see Log and Revision Filtering.Putting slow, whole-project checks in a pre-commit hook: hooks are local and skippable, so anything that must hold belongs in CI or a server-side hook.
This guide assumes a current Git 2.x release. A handful of changes along the 2.x line still come up, because interviewers learned Git at different points and teams run different versions: - **2.0** made `push.default=simple` the default, so a bare push sends only the current branch to its upstream, and made `git add` on a path stage removals as well. - **2.23** added `git switch` and `git restore`, splitting the branch-switching and file-restoring jobs that `git checkout` had combined. Older answers use checkout for both; either is correct if you name what it does. - **2.28** added `init.defaultBranch`, which is why new repositories may start on `main` or `master` depending on configuration and hosting defaults. - **2.29** introduced SHA-256 repositories as an experimental object format; SHA-1 remains the default and interoperability between the two is still limited. - **2.34** made `ort` the default merge strategy, replacing `recursive` for ordinary two-branch merges. When an answer depends on one of these — the command you would type, the push behaviour, the default branch name — say which era you are describing.
Git replaced centralised systems such as Subversion and CVS for most software work. The trade-off interviewers expect you to name: a centralised system keeps one authoritative history on a server and supports path-level locking, while Git gives every clone full history, cheap local branches and offline work, at the cost of weaker handling of large binary files and no built-in locking. Mercurial is the closest distributed peer and is far less common today; Perforce remains common where huge binary assets dominate, as in game development. Around Git sit the hosting platforms — GitHub, GitLab, Bitbucket and self-hosted servers — which add pull or merge requests, review, branch protection and CI. None of those are Git features, and a good answer keeps the line clear: a protected branch is a server policy, a pull request is a hosting-platform object, while a ref and a hook belong to Git. Git LFS stores large files outside the repository behind small pointer files, and hook managers such as husky, lint-staged and the pre-commit framework distribute client-side checks across a team. At large scale, partial clone, sparse checkout and monorepo tooling address repositories that outgrow a plain full clone.
explore
- Object Model and DAG27 questions
- Blobs, Trees, Commits, and Tags5 questions
- Refs, HEAD, and Branch Pointers3 questions
- The Commit DAG and Revision Selection5 questions
- Inside the .git Directory4 questions
- Packfiles, GC, and Reachability5 questions
- Plumbing Commands5 questions
- Staging and Commits18 questions
- Working Tree, Index, and HEAD4 questions
- Partial and Interactive Staging5 questions
- Amend, Fixup, and Squash5 questions
- Commit Messages and Trailers4 questions
- Branching and Merging26 questions
- Branches as Pointers5 questions
- Merge Base and Three-Way Merge5 questions
- Fast-Forward vs Merge Commit5 questions
- Merge Strategies and Options5 questions
- Conflict Anatomy and Resolution6 questions
- Rebase and History Rewriting32 questions
- How Rebase Replays Commits6 questions
- Interactive Rebase6 questions
- Cherry-Pick and Revert6 questions
- Bulk History Rewriting5 questions
- Force-Push Safety5 questions
- Bisect4 questions
- Remotes and Collaboration35 questions
- Remotes and Refspecs4 questions
- Fetch vs Pull5 questions
- Tracking Branches and Divergence5 questions
- Push Semantics6 questions
- Clone, Shallow, and Partial Clone5 questions
- Transports and Credentials6 questions
- Forks and Upstream Sync4 questions
- Stash, Reflog, and Recovery20 questions
- Stash5 questions
- Reset, Restore, and Clean5 questions
- Reflog5 questions
- Recovering Lost Work5 questions
- Inspecting History16 questions
- Log and Revision Filtering5 questions
- Diffing and Comparing6 questions
- Blame and Line Archaeology5 questions
- Hooks13 questions
- Client-Side Hooks5 questions
- Server-Side Hooks4 questions
- Hook Managers4 questions
- Submodules, Subtrees, and Worktrees13 questions
- Submodules5 questions
- Subtrees and Vendoring4 questions
- Worktrees4 questions
- Branching Workflows20 questions
- Trunk-Based Development4 questions
- Git Flow, GitHub Flow, GitLab Flow5 questions
- Release Branches, Tags, and Backports6 questions
- Forking and Patch Contribution5 questions
- Configuration, Ignore Rules, and Attributes25 questions
- Config Scopes and Aliases6 questions
- Ignore Rules5 questions
- gitattributes5 questions
- Line Endings Across Platforms4 questions
- Signing Commits and Tags5 questions
- AI & Data Scientistroleanchors this topic
- AI Engineerroleanchors this topic
- AI Red Teamingroleanchors this topic
- Android Developerroleanchors this topic
- Backend Developerroleanchors this topic
- Data Analystroleanchors this topic
- Data Engineerroleanchors this topic
- DevSecOps Engineerroleanchors this topic
- Frontend Developerroleanchors this topic
- Full Stack Developerroleanchors this topic
- Game Developerroleanchors this topic
- Git & GitHubskillanchors this topic
- Java Backend Developerroleanchors this topic
- Java SDETroleanchors this topic
- Kotlin Backend Developerroleanchors this topic
- MLOps Engineerroleanchors this topic
- Machine Learning Engineerroleanchors this topic
- Network Engineerroleanchors this topic
- PostgreSQL DBAroleanchors this topic
- QA Engineerroleanchors this topic
- Software Architectroleanchors this topic
- iOS Developerroleanchors this topic
- BI Analystrole
- Blockchain Developerrole
- DevOps / SRE Engineerrole
- Vibe Codingskill
questions
245 · 11 sectionsIn Git, what does a commit record about its predecessors, and why is history a DAG?
basics
~20 sEach Git commit stores an ordered list of parent commit IDs: zero for a root commit, one for an ordinary commit, two or more for a merge. Following those pointers backwards yields a directed acyclic graph, not a straight line.
In Git, what is HEAD, and how does it differ from a branch name?
basics
~20 sHEAD is a pointer to whatever you currently have checked out. Normally it is a symbolic ref holding the name of a branch, such as refs/heads/main, while the branch itself is a ref holding one commit hash.
In Git, what is the difference between HEAD~2 and HEAD^2?
basics
~20 sIn Git, HEAD~2 walks two steps back along the first-parent chain, i.e. the grandparent. HEAD^2 takes one step to the second parent, which exists only on a merge commit; on a non-merge it is an error.
In git log, what does main..feature select, and how does main...feature differ?
basics
~20 sIn git log, main..feature lists commits reachable from feature but not from main. main...feature lists the symmetric difference: commits reachable from either side but not both. In git diff, three dots means something else — merge base against the right side.
In Git, what does a commit object actually store?
basics
~10 sA commit stores the hash of one tree (a full snapshot of the tracked files), the hashes of its parent commits, author and committer identity with timestamps, and the message. It stores no diff.
What does git commit --amend --no-edit do, and why does the commit SHA change?
basics
~20 sgit commit --amend replaces the tip commit with a brand-new commit built from the current index, and --no-edit reuses the old message. A commit's name is a hash of its whole content, including the committer timestamp, so the replacement gets a new SHA.
How should a Git commit message be structured, and what is the 50/72 convention?
basics
~20 sA Git commit message is a short subject line, a blank line, then an optional body. The convention keeps the subject under about 50 characters and wraps body lines at 72. The blank line is the part Git itself depends on.
In Git, how do git add -A, git add -u, and git add . differ?
basics
~20 sIn modern Git, add -A stages new, modified and deleted paths across the whole working tree; add -u stages modifications and deletions for already-tracked paths only, never new files; add . does what -A does but limited to the current directory and below.
In Git, what are the working tree, the index, and HEAD?
basics
~20 sGit juggles three trees: the working tree (your files on disk), the index or staging area (the proposed next commit), and HEAD (the commit you are on). git add copies working tree into index; git commit turns the index into a commit.
What does git add -p do, and why would you stage only part of a file?
basics
~20 sgit add -p walks the diff between your working tree and the index hunk by hunk and asks whether to stage each one. Only the accepted hunks enter the index, so one messy file can become several focused commits.
In Git, what does creating a branch with git branch feature actually do?
basics
~20 sIt writes one new ref holding the hash of the commit you branched from. No files are copied and no history is duplicated, which is why branching is instant in a repository of any size.
In Git, what do the <<<<<<<, =======, and >>>>>>> markers in a conflicted file mean?
basics
~20 sGit writes both versions of a region it could not merge into the file. Text between <<<<<<< and ======= is the side you are on; text between ======= and >>>>>>> is the incoming side. You edit the file to the final content, delete the markers, and stage it.
In Git, what is a fast-forward merge and when can Git perform one?
basics
~20 sA fast-forward merge happens when the current branch's commit is already an ancestor of the commit being merged. Git records no merge commit; it simply moves the branch pointer forward and updates the index and working tree.
In Git, what is a three-way merge and which three commits does it use?
basics
~20 sA three-way merge combines two branch tips using their best common ancestor, the merge base, as a reference point. Comparing each tip against that base tells Git which side changed what, so it can combine changes instead of guessing.
In Git, what is a detached HEAD and how do you rescue commits made in one?
basics
~20 sHEAD is detached when it names a commit directly instead of a branch, so commits you make advance nothing. Rescue them by creating a branch at that commit — git switch -c <name> before leaving, or git branch <name> <hash> from the reflog afterwards.
In Git, what does git cherry-pick do to the commit you name?
basics
~20 sIt applies that commit's change on top of your current branch and creates a new commit for it. The original commit stays where it is; the copy has a different SHA because its parent, committer and timestamp differ.
In Git, why is force-pushing to a shared branch dangerous?
basics
~20 sA forced push overwrites the remote branch pointer even when the new tip is not a descendant of the old one, so commits other people pushed can stop being reachable and everyone who already fetched the branch now has a history that diverges from it.
In Git, what happens when you run git rebase -i HEAD~3?
basics
~20 sGit opens an editor holding a todo list of the three commits after HEAD~3, oldest first, each on a pick line. You edit the verbs and the order, save, and Git replays the commits as scripted, creating new commit IDs.
In Git, what is the difference between merging main into your branch and rebasing onto it?
basics
~20 sMerging adds a new commit that joins both histories and leaves your existing commits untouched. Rebasing re-creates your commits on top of main's tip as new commits with new hashes, producing a straight line with no merge commit.
In Git, why does deleting a file and committing not remove it from history?
basics
~20 sA Git commit only adds a new snapshot. Every earlier commit still references the blob holding that file, so the content stays reachable and clonable until history itself is rewritten and the old objects are pruned.
In Git, what does cloning with --depth 1 actually download, and what is missing?
basics
~20 sgit clone --depth 1 downloads only the tip commit of a single branch plus the trees and file contents needed to check it out. Older history and other branches are absent, so log and blame reach back one commit.
What is the difference between git fetch and git pull?
basics
~20 sgit fetch downloads new objects and updates remote-tracking refs such as origin/main, leaving your branch and working tree untouched. git pull runs that same fetch and then immediately integrates the result into your current branch by merging or rebasing.
In a forked repository, what do the Git remotes named origin and upstream conventionally point to?
basics
~10 sBy convention origin is your own fork, the copy you can push to, and upstream is the original project you forked from and normally only fetch from. Git gives neither name any special meaning.
In Git, how do you delete a remote branch, and what does git push origin :feature mean?
basics
~20 sUse git push origin --delete feature. The older equivalent, git push origin :feature, is a refspec with an empty source: pushing nothing onto the destination ref deletes it. Both remove only the remote branch, never your local one.
In Git, what does git remote add origin <url> actually change in your repository?
basics
~20 sIt only edits .git/config, adding a remote section with a url and a default fetch refspec. No network call happens and no objects arrive until you run git fetch, and the name origin is purely local.
After git reset --hard discarded your last three commits, how do you get them back?
basics
~20 sNothing was deleted: git reset --hard only moved the branch pointer. Find the old tip's hash with git reflog, verify it with git show, then re-anchor it using git branch rescue <hash> or git reset --hard <hash>.
In Git, how does git reflog differ from git log?
basics
~20 sgit log walks commit ancestry from a ref, showing shared project history. git reflog lists a local journal of where HEAD or a branch has pointed over time, newest first, including commits no longer reachable from any branch.
In Git, how do you unstage a file without losing the edits in your working tree?
basics
~10 sRun git restore --staged <file>. It rewrites that path in the index from HEAD, leaving the file on disk exactly as you edited it. The older equivalent is git reset -- <file>.
In Git, what is the difference between git stash pop and git stash apply?
basics
~20 sBoth restore a saved stash into your working tree; pop also deletes the stash entry afterwards, while apply leaves it in the list. If a pop hits a conflict, the entry is kept, so nothing is lost.
In Git, how does HEAD@{2} differ from HEAD~2?
basics
~10 sHEAD~2 is graph navigation: two commits back along parent links from the current commit. HEAD@{2} is reflog navigation: the commit HEAD pointed at two ref movements ago, regardless of ancestry.
What does git blame report for each line, and what can it not tell you?
basics
~20 sgit blame annotates every line of a file with the commit that last modified it, plus that commit's author and date. It shows only the most recent touch, never the line's full history, and it says nothing about deleted lines.
What does git diff show by default, and how does git diff --staged differ?
basics
~20 sPlain git diff compares the working tree against the index, showing changes you have not staged yet. git diff --staged (identical to --cached) compares the index against HEAD, showing exactly what the next commit would contain.
What do the git log flags --oneline, --graph, and --decorate each add to the output?
basics
~20 sIn git log, --oneline prints one abbreviated-hash-plus-subject line per commit, --graph draws the commit DAG as ASCII art down the left margin, and --decorate appends the ref names — branches, tags, HEAD — that point at each commit.
What does git show display for a commit, and how does it differ from git diff?
basics
~20 sgit show prints one object: for a commit it prints the metadata and log message plus the patch against its first parent. git diff prints only a patch between two snapshots and never shows commit metadata.
How do you make git blame skip a mass-reformatting commit?
basics
~20 sList the reformatting commit's full id in a file and point Git at it: git blame --ignore-rev <sha>, or --ignore-revs-file <file>, or set blame.ignoreRevsFile so it applies automatically. Blamed lines are then attributed to the previous commit that touched them.
In Git, what happens when a client-side hook such as pre-commit exits with a non-zero status?
basics
~10 sA non-zero exit from a pre-operation hook such as pre-commit, commit-msg or pre-push aborts the operation — no commit is created, no push is sent. Post-hooks like post-commit run afterwards and cannot abort anything.
How do Git's pre-commit, prepare-commit-msg and commit-msg hooks differ during one git commit?
basics
~20 sThey fire in that order during one git commit: pre-commit inspects the staged content before any message exists, prepare-commit-msg seeds or rewrites the message file before the editor opens, and commit-msg validates the final message. All three can abort by exiting non-zero.
In Git, how do the pre-receive and update hooks differ on the repository receiving a push?
basics
~20 spre-receive runs once per push and reads every proposed ref update on stdin, so a non-zero exit rejects the whole push. update runs once per ref with the ref name and old and new object names as arguments, and rejecting there blocks only that one ref.
What does lint-staged run your checks against, and why use it in a Git pre-commit hook?
basics
~20 slint-staged runs the commands you configure only against the files currently staged in Git's index, not the whole project. That keeps a pre-commit hook proportional to the change, so it finishes fast and only reports problems in code you touched.
After cloning a repo with Git submodules, why are the submodule directories empty?
basics
~20 sA plain clone fetches only the superproject, which records submodules as commit references rather than files, so it creates the directories but leaves them empty. Clone with --recurse-submodules, or run git submodule update --init --recursive afterwards.
What does git worktree add create, and how does it differ from a second git clone?
basics
~20 sIt creates an additional working directory with its own checked-out branch, backed by the same repository. Unlike a second clone it shares one object database and one set of branches, so it costs no extra fetch and no duplicated history.
What does a Git submodule actually store inside the parent repository's commit?
basics
~20 sOnly a commit SHA. The parent's tree holds a special gitlink entry, mode 160000, recording which commit of the other repository belongs at that path. The URL to fetch it from lives separately, in the tracked .gitmodules file.
What are the trade-offs of git subtree versus git submodule for someone who only clones your repo?
basics
~20 sSubtree stores the dependency's actual files in your repository, so a plain clone builds immediately; submodules store only a pinned pointer, so consumers need an extra recursive step. Subtree costs repository size and a mixed history.
In Git, which branches does the Git Flow model define and what is each one for?
basics
~20 sGit Flow defines two permanent branches, main and develop, plus three temporary types: feature branches cut from develop, release branches cut from develop, and hotfix branches cut from main. Releases and hotfixes merge back into both permanent branches.
Why doesn't a new Git tag like v1.4.0 reach the remote after git push, and how do you send it?
basics
~20 sA plain git push sends branch refs only; tags live in refs/tags and are excluded by the default refspec. Push one explicitly with git push origin v1.4.0, or push a branch plus its reachable annotated tags with git push --follow-tags.
What is trunk-based development, and how long do its branches live in Git?
basics
~20 sTrunk-based development means everyone integrates into one shared branch — the trunk, usually main — continuously. Branches off it are short-lived, typically merged back within a day or two, so the repository never accumulates long-running parallel lines of development.
In Git, what does git format-patch produce, and how does a maintainer apply it?
basics
~20 sgit format-patch writes one mbox-formatted file per commit, containing the message plus the diff and author metadata. A maintainer replays them with git am, which recreates the commits with their original author, date and message rather than just applying a diff.
How do you split a large Git change into a series of commits a maintainer can review?
basics
~20 sMake each commit one self-contained step that builds and passes tests on its own: preparation and refactoring first, behaviour change second, then tests and docs. Order them so a reviewer reading top to bottom sees the change being argued, not assembled.
Configuration, Ignore Rules, and Attributes
all 25 Configuration, Ignore Rules, and Attributes questions →In Git, how do the --system, --global and --local config scopes differ, and which one wins?
basics
~10 sThey name three config files: machine-wide, per-user, and per-repository. Git reads them in that order and the narrower scope wins, so a repository's .git/config overrides your home-directory settings, which override the system file.
In Git, why does adding an already-tracked file to .gitignore have no effect?
basics
~20 sGit ignore rules apply only to untracked paths. Once a file has an entry in the index, Git keeps reporting and committing its changes whatever .gitignore says. Untrack it with git rm --cached, then commit that removal.
In Git, why does a file show every line as changed after a Windows teammate edits it?
basics
~10 sThe file's line endings switched between LF and CRLF. Git compares whole lines, so an invisible carriage return at the end of every line makes every line differ and the whole file looks rewritten.
In Git, what does a .gitattributes file control, and how are its rules resolved?
basics
~10 sA .gitattributes file assigns per-path attributes that change how Git diffs, merges, filters and archives matching files. Patterns use .gitignore syntax; within one file the last matching line wins, and .git/info/attributes outranks committed files.
In a Git .gitignore file, what do a leading slash, a trailing slash, and ** match?
basics
~20 sA leading slash anchors a Git ignore pattern to the directory holding the .gitignore instead of matching at any depth. A trailing slash restricts the match to directories. Double asterisk matches across directory separators, which a single asterisk never does.