app.py<<<<<<< HEADgreet = "Hi"=======greet = "Hello">>>>>>> featureprint(greet)originmain → BDAD′BGCEMFfeaturemainHEAD
Commits: saved snapshots, each linked back to its parentBranch labels (main, feature) and HEAD: movable pointersapp.py card: the conflict markers, then the fixed fileorigin: the remote copy on a serverEach commit points back to its parent. A branch is a small movable label that points at one commit, and HEAD rides on the branch you are on. Watch the labels: committing moves only the branch HEAD is on; a fast-forward merge just slides main forward; when both branches have new work, merging makes commit M with two parents. The conflict card shows the markers Git writes when both sides changed the same line. Rebase is shown as the other choice: D is replayed on top of E as D′. Push and pull carry commits to and from the remote, origin; at the end new commit G goes up for review in a pull request. Commit ids in the examples (such as 7b9e41d) are made up and shortened. Real ids are 40-character hashes, so yours will differ.

Branches are pointers

  1. Each commit is a saved snapshot of your project that points back to its parent. A branch is just a name that points at one commit. Here the branch main points at commit B, the newest.

Merging

Sharing

Try it in a terminal

;; step 1/12 · A branch is a pointer
$ git branch
* main
$ cat .git/refs/heads/main   # a branch is a tiny file
7b9e41d...                     # the id of commit B

Commit ids in the examples (such as 7b9e41d) are made up and shortened. Real ids are 40-character hashes, so yours will differ. A rebased commit gets a new id because its parent changed. If D and E clash, rebase stops with the same conflict, and you resolve it, git add, then git rebase --continue.