1 Git Version Control
Published:
git diff
shows unstaged changes- compares to the last commit if staging area empty (if haven’t
git add
ed) git diff --cached
shows staged changes
- compares to the last commit if staging area empty (if haven’t
Branching
git branch dev
Creates a new branch dev
that diverges from main
Merge to
main
when thedev
branch is readygit branch
to list all branchesgit switch dev
switches to branchdev
When we make some changes to hello.c
on the dev
branch and commit, dev
is ahead of main
by one commit.
HEAD
is the tip of the current branch, where the working directory is
git log
lists all commits that are in the current branch, not other branches
Merge
Every commit (except the root) has a parent. Sometimes you have two parents
# inside main branch
git merge dev
- If there’s a conflict, you need to resolve the conflict Now
git log
, you’ll see a new merge commit git log --graph
- The merge commit has two parent commits.
git log
will show the commits ondev
because they are now reachable After merging withmain
,dev
is still here - The merge is not shown in the log of
dev
Detached HEAD
HEAD
does not always refer to the tip of some branch. It means what you are looking at right now
- stored in
.git/HEAD
filegit switch --detach <commit>
- If
git log
, you’ll see only the changes up to that point - If
git status
, it tells “HEAD detached at <>”
You can make commits from that detached head, without branching
- You can make this into a branch later
- But if you switch before making into branch, they will be deleted
Git objects
.git
: a directory containing all files and metadata Store file contents and metadata (commit)
- Name: SHA-1 hash of their contents, unique digital footprint
git hash-object hello.c
hashes thehello.c
tree .git/objects/
git cat-file -t <hash>
tells the type of the file-p
prints the content of the file to human readable format- Pointer to a tree object: git’s internal representation of a directory’s contents
- Pointer to the parent object
Tree object:
git cat-file -p <tree>
# 100644 blob 80c5b23a2ed852b4d5afd76dde6b85e321e13ce3 hello.c
blob
: contentstateDiagram-v2 Commit --> Tree Tree --> Makefile Tree --> hello.c
If a commit didn’t do anything with
Makefile
, itstree
will point to the same file blob- Git only stores one version once
- If the content changes (
hello.c
), Git will create an entire new blob- Git will periodically pack similar objects to save space
Subdirectories
When subdirectories are created, cd’s tree
object will also point to the tree
of the subdir.
- If same file content in both directories, their
tree
s will point to the same object.
Index
Staging revisited git ls-files
lists all files being tracked by Git git ls-files --stage
shows all what to be in .git/index
if there’s nothing in the staging area
git ls-files --stage
# 100644 850742712c6609bf85aecca7c24c2eebf4d89b0a 0 Makefile
# 100644 9b1d2628d4bfb5cd74a2c7138ce0572a89676554 0 hello.c
# 100644 8baef1b4abc478178b004d62031cf7fe6db6f903 0 subdir/notes.txt
Staging areas has all the files in the repository, and their hashes
Now modify hello.c
git diff
diff --git a/hello.c b/hello.c
index 6aa1b98..c9f149c 100644
--- a/hello.c
+++ b/hello.c
6aa1b98..c9f149c
: Git quickly calculates the new hash. If they are different, Git compares the files.
By adding the file, Git creates a blob
- When a version of the file is in index/staging, you still have the version in the file system, only referred to by the
index
file.
References
.git/refs/heads
contains files named after branches- Each file is the hash of the latest commit on that branch
.git/HEAD
: a text file with the path to the currentHEAD
- Attached:
HEAD
will refer to a branch file path, which points to a commit - Detached: it will be a hash for a commit To Git, a branch is simply the single latest commit.
- Attached:
- You can always trace back to its parent.
GitHub
Website to host your repo git clone <old> <new>
Push pull are clumsy.
- Create a central, shared repo between people. Each person push and pulls from it.
Setup
Copy the SSH URL, uniquely representing this GitHub repo
git clone git@github.com:mgongd/centralrepo.git
Add this GitHub repo as a remote repo named origin
git remote add origin git@github.com:mgongd/centralrepo.git
git remote
will return “origin”- as if the central repo comes there by cloning
For the first push, need to associate local main branch with a remote branch
git push --set-upstream origin main
git push
will be fine for subsequent pushes
In .git/config
, Git tracks the remote origin stuff.
After making another change and commit, on GitHub, the origin/master
branch is behind.
- Remote
main
branch pointer is in.git/refs/remotes/origin/main
Collaboration
As a teammate,
git clone
the repo- Create and switch to a new branch
git switch dev
- Make some changes
git push -u origin dev
(-u
is shorthand)- Create a pull request. Request review from others
- Alternatively, you can merge
dev
withmain
locally and push frommain
to GitHub
- Alternatively, you can merge
- Once agreement, merge the branch and close the request
- Create a merge commit: similar to local
- Squash and merge: get rid of the intermediate branches, creates a meta commit containing all changes in that branch. Just preserve the end result
- Rebase and merge: If
main
has moved ahead, take thedev
change, appending them after themain
changes, pretend you make them later on (fast forwardmain
)
- Go back to master, and
git pull