Announcements #
- GitHub Bug and Plan B (success!?)
- Office hours: Wed 3
- This Week’s Plan
Plan for Today #
- Quick Review of Version Control
- Git demo
- Unit Testing [next time]
Quick Review of Version Control #
- The Three Trees
Staging: Working Tree => Index
Committing: Index => HEAD
Checkout: HEAD => Working Tree
- Common Git Commands
git status Get current state of repo and three trees git log Look at repository history git diff See what has changed between commits git init Initialize a new repository git add Stage one or more files git branch Create and manage branches git switch Switch branches git checkout Checkout a commit git commit Commit the current index git merge Combine changes from multiple commits git remote Associate repo with a remote repo git push Send new commits to a remote copy of this repo git fetch/pull Receive new commits from a remote repo git worktree Work on multiple branches at the same time - Good Practice
- Good Commit Messages (think of future you!)
- Commit Often
- Use and merge branches to explore alternative lines of development
Git Demo (Learning By Doing) #
Cloning the Repo #
-
Clone (download) an existing repository:
cd ~/s750 git clone https://github.com/36-750/git-demo.git cd git-demo/ # move into the cloned repository git status # check the status ls -a # observe the .git hidden directory
-
Open the
git-demo
folder in Explorer or Finder or whatever you use on your computer to find files. Look – it’s the same stuff.
A Quick Look at the Plumbing #
-
Every git object (blobs, trees, commits, and tags) is stored as an indexed piece of data in the .git directory, indexed by its hash value.
ls .git ls .git/objects echo 'We can add objects at will' | git hash-object -w --stdin # creates a new object # prints hash =># 312b5389b6c43a4bf8867f6c607fcf2efd67824f ls .git/objects/31 # first two digits of the hash is a directory git cat-file -p 312b5389b6c43a4bf8867f6c607fcf2efd67824f # use your hash if different
-
HEAD points to a commit, refs
cat .git/HEAD # shows a "ref", a friendly alias for a commit cat .git/refs/heads/main # this contains the (less friendly) hash git cat-file -p 655eca13a3622464056a0d5a1d60cccd582aebe6 # what is in the commit?
-
We can see the tree at the current main branch
git cat-file -p 'main^{tree}' # Don't forget the quotes
-
Immutable structure sharing in action
echo 'version 1' > test.txt git hash-object -w test.txt #=> 83baae61804e65cc73a7201a7252750c76066a30 echo 'version 2' > test.txt git hash-object -w test.txt #=> 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a find .git/objects -type f # both versions are there! rm test.txt git status # Not a visible change because no file git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt cat test.txt git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt cat test.txt rm test.txt
Basic Operations #
-
Make a branch and switch to it.
git branch your-clever-name-here # Create a branch git branch # Look at available branches, main still current git switch your-clever-name-here # Switch to the branch git status
We are now working on the branch, but since we haven’t changed it,
main
andyour-clever-name-here
are pointing to the same commit. -
Advance the
your-clever-name-here
branch by two commitsgit cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt git status # see what is highlighted git switch main # test.txt is 'untracked', so when we switch it 'follows' git switch your-clever-name-here git add test.txt # staging test.txt git status # note the differnce git commit -m 'meta: added a test version descriptor' git status git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt git add test.txt # staging test.txt, you need to stage again (cf. Three Trees) git diff # Look at the differences git commit -m 'meta: updated test version descriptor' git status git log --oneline --color --graph --branches
-
Change your work but try to switch before committing
echo 'version 3' > test.txt git switch main # oops git add test.txt git commit # try out your editor config, enter comit message and close the file git switch main # good now git log --oneline --color --graph --branches
Look at your working directory in this branch. Switch back and forth and compare. Go back to
main
. -
Create a new branch named
YOURNAME-demo
offmain
and switch to it. (Replace YOURNAME with your github username.)git branch YOURNAME-demo git switch YOURNAME-demo
This will be our reference branch for this exercise, playing the role that
main
would play in practice. (Avoids conflicts -
Make a new branch and switch to it.
Make some changes to your repository. Add files, edit something, whatever. Stage and commit the files. Do it one more time, two commits on the new branch.
Switch back to YOURNAME-demo.
git log --oneline --color --graph --branches
-
Merge the
your-clever-name-here
branch back into YOURNAME-demo. This should have no conflicts.git merge
will merge the specified branch into the current branch.git switch YOURNAME-demo git status # check we are where we think we are!! # if we were working with a remote, git pull to ensure we have the latest version git merge your-clever-name-here git log --oneline --color --graph --branches
You could delete the old branch if you like with
git branch -d
, though you do not have to. For today, keep it for later. -
Make a new branch off YOURNAME-demo, switch to it, and change an existing file, commit. Switch back to YOURNAME-demo and change that same file. Commit. Merge the new branch into YOURNAME-demo. Suppose you called the branch
conflict
.git switch YOURNAME-demo git status git merge conflict # Surprise... conflict?
Look at the conflicting file. Edit out the markers and commit it. The merge will continue. You can abort a merge with
git merge --abort
. Note: you have to stage the edited file.git log --oneline --color --graph --branches
-
In
YOURNAME-demo
, add some changes to the index, so they are staged to be committed. Then commit the changes.git status git add file_you_changed.py git commit
-
Make more changes and stage them.
-
Look at differences
git log --oneline --color --graph --branches git diff 3597a84 e3f8f5d # replace any two hashes you want to compare git diff # how is this diff different :?)
Commit if you like.
-
Push this branch to the remote repository (on GitHub)
git push --set-upstream origin YOURNAME-demo
The
--set-upstream
option is only necessary once, to tell Git that the “upstream” for this branch – the remote location for it – is the corresponding branch on GitHub, which will be created automatically. -
Switch back to the main branch:
git switch main ls
Now look at the files in your repository. Notice they’ve all changed back to what they looked like before you switched to your branch.
-
Look at the status
git status git log --oneline --color --graph --branches
-
Make a pull request on GitHub
This is similar to the workflow we’ll use for submitting homework. We’ll provide you a script that automates part of it, but it’s good to know basic Git operations so you know what’s going on when you switch branches and submit homework.
Work Trees #
Working with branches can sometimes be tricky because one has changes in progress that keep you from switching branches when you want to.
git-worktree
simulates working with multiple branches simultaneously by storing
linked repositories in another directory. Start in main
.
-
Pick two of the branches you created in the demo above. I’ll call them
foo
andbar
. Create work treesmkdir ../worktrees-git-demo git worktree add ../worktrees-git-demo/foo foo git worktree add ../worktrees-git-demo/bar bar
Branches
foo
andbar
are now checked out in those directories. -
Move to one and commit some changes
cd ../worktrees-git-demo/foo # I like to keep my worktrees elsewhere but YMMV # make and commit changes git status
If you go back to the main git-demo directory and try to
git switch foo
. It won’t let you;foo
is already spoken for.cd ~/s750/git-demo git worktree remove ../worktrees-git-demo/foo git switch foo ls # Notice the changes (in whatever way) git switch main
This is a useful workflow for your homework. For each branch you are working on, create a worktree and work there. E.g.,
cd ~/s750
mkdir exercises # directory for your active exercises
cd assignments-YOURNAME
git worktree add ../exercises/ex-name ex-name
cd ../exercises/ex-name
# work on it
When done, remove the worktree. Create it again if you need to work on the exercise.
Resources #
- Reference Notes on Version Control
- Learn Git Branching is a very nice interactive tutorial, with diagrams!
- The Software Carpentry Git lesson walks you through basic Git operations on your computer
- ProGit is a full book about Git that you can read online
- The Git Reference Manual lists every single Git command and its options
- GitHub’s Git Cheat Sheets explain some of the common commands
- Dangit, Git! explains how to fix common Git problems you may encounter
man git-log
at command line, or more generallyman git-X
.
We recommend trying the git-challenge
homework assignment and referring to the
resources above as you do it, so you understand each step you’re taking.