- Up-to-date installation instructions for Git and Bash are available here: https://libguides.ucmerced.edu/software-carpentry/git/install
- Create a Github account here: https://github.com/
- Broadly speaking, there is a tension between making computer systems fast and making them easy to use.
- A common solution is to create a 2-layer architecture: A fast, somewhat opaque core surrounded by a more friendly scriptable interface (also referred to as “hooks” or an “API”). Examples of this include video games, Emacs and other highly customizable code editors, and high-level special-purpose languages like Stata and Mathematica.
- Unix shell is the scriptable shell around the operating system. It provides a simple interface for making the operating system do work, without having to know exactly how it accomplishes that work.
- Minimal example: https://swcarpentry.github.io/shell-novice/02-filedir/index.html
- “directory” == folder
- Your files are in “/home/<your login>”or “/Users/<your login>”
- Trees are upside-down in computer science
whoami
pwd # Print Working Directory
Command flags modify what a command does.
ls # List directory contents
ls -a # ... and include hidden files
man ls # Manual for "ls"
ls --help # In-line help info; should work in Windows
- You can navigate through the man page using the space bar and arrow keys
- Quit man with “q”
- Online references are available for Windows users who don’t have man pages: https://linux.die.net/
When a command is followed by an argument, it acts on that argument.
cd Desktop
ls *.pdf # List all files ending in ".pdf"
cd .. # go up one directory
The terminal saves your command history (typically 500 or 1000 commands)
- You can see previous commands using the up/down arrows
- You can edit the command that’s currently visible and run it
Once your command history gets big, you might want to search it:
history
history | grep ls # pipe the output of history into search
- Move backwards and forwards in time using snapshots of your code
- Control what goes into a snapshot
- Collaborate
- Explore alternative versions of your project without destroying prior work
- Useful for text files, less useful for binary files (most of the useful features are text-oriented)
All git commands are 2-part verbs, followed by flags and arguments:
git config --global user.name "Gilgamesh"
git config --global user.email "[email protected]"
git config --global core.autocrlf input # Unix and MacOS
git config --global core.autocrlf true # Windows
You can use any text editor, but you want a sensible default in case Git opens one for you:
git config --global core.editor "nano -w"
Only push the current branch (more about this later):
git config --global push.default "simple"
git config --list # or -l
git config --list --show-origin # where is this setting coming from?
We are going to create and track plans for our quarantine garden.
cd ~/Desktop
mkdir garden
cd garden
git init
ls
ls -a
Git uses this special subdirectory to store all the information about the project, including all files and sub-directories located within the project’s directory. If we ever delete the `.git` subdirectory, we will lose the project’s history.
git status
touch shopping_list.txt
nano shopping_list.txt
1. Cherry tomatoes
Save and quit. You can verify that you’ve saved your changes in Bash:
ls
cat shopping_list.txt
git status
git add shopping_list.txt
git status
git commit -m "Start shopping list for garden"
git status
- Commit messages should be useful; eventually there will be a lot of them (we’ll come back to this)
Draw working tree, staging area (index), and repository commit (no history yet)
# Concicse help
git add -h
# Verbose help
man git-add
Edit with editor of your choice:
1. Cherry tomatoes 2. Italian basil
git status
git diff
# If you try to commit the file before you add it to the Staging area,
# nothing happens:
git commit -m "Add basil"
git status
# Add file to Staging area, then commit:
git add shopping_list.txt
git commit -m "Add basil"
Update drawing with repository history going back in time (H, H~1, H~2…)
1. Cherry tomatoes 2. Italian basil 3. Jalapenos
# By default, "diff" shows changes to Workspace
git status
git diff
# Once the file is added to Staging, "diff" no longer shows changes
git add shopping_list.txt
git status
git diff
# You can examine Staging instead
git diff --cached # or "--staged"
git commit -m "Add peppers"
git status
- Staging area is for creating sensible commits. You can edit multiple files and only add a subset of them to a given commit. This makes it easier to look back at your work.
git log
git log --oneline
git log --oneline --graph
git log --author=~Derek Devnich
git log --since=5.days # or weeks, months, years
- You can identify commit by unique ID or by HEAD offset
- HEAD is a pointer to the most recent commit
Try to commit an empty directory:
mkdir flowers
git status
git add flowers
git status
Now add files and try again:
touch flowers/roses flowers/tulips
git status
ls flowers
git add flowers
git commit -m "Initial thoughts on flowers"
1. Cherry tomatoes 2. Italian basil 3. Jalapenos 4. Cayenne peppers
cat shopping_list.txt
# Identical to "git diff" with no argument
git diff HEAD shopping_list.txt
# Show all changes back to this point
git diff HEAD~1 shopping_list.txt
git diff HEAD~3 shopping_list.txt
# Show changes for just HEAD~3
git show HEAD~3 shopping_list.txt
# Show changes in range of commits
git diff HEAD~3..HEAD~1 shopping_list.txt
git log HEAD~3..HEAD~1
git diff f22b25e3233b4645dabd0d81e651fe074bd8e73b shopping_list.txt
# Use reduced ID from "git log --oneline"
git diff f22b25e shopping_list.txt
git status # We have unstaged changes
# Revert the working tree to the most recent commit
git checkout HEAD shopping_list.txt
cat shopping_list.txt
git checkout f22b25e shopping_list.txt # or "git checkout HEAD~3 shopping_list.txt"
cat shopping_list.txt
# These changes are also in the Staging area; do a commit if you want to keep
# this older version
git status
git checkout HEAD shopping_list.txt # get back the new version
Update drawing with files moving in and out of working tree/staging area
What if you want to see a previous version of the whole project?
# Detached HEAD moves the whole HEAD pointer back to an earlier version
git checkout HEAD~2
git status
# Move HEAD back to latest commit by checking out the branch name
git checkout master
- Unfortunately some of these terms, like “checkout”, are overloaded. Think about what you want to do to your history, then look up the appropriate command.
Update drawing with moving HEAD pointer
git checkout -b feature # equivalent to "git branch feature" + "git checkout feature"
git branch # Show all branches
git status
touch feature.txt
nano feature.txt
This is a new feature we're trying out
git add feature.txt
git commit -m "Added a trial feature"
ls # We have a new file
git checkout master
ls # File doesn't exist on the master branch
git merge feature
ls # Merging the feature branch adds your changes
- This is simplest possible case; all of the new changes were in one branch
Draw the branch history with the merge (Fast-Forward merge moves branch tag) Draw a branch history with competing changes (Recursive merge resembles octopus graph)
mkdir results
touch a.dat b.dat c.dat results/a.out results/b.out
ls
git status
touch .gitignore
ls -a
*.dat results/
# We are ignoreing .dat files and tracking .gitignore
git status
git add .gitignore
git commit -m "Ignore output files"
- Ignoring complicated directory structures can be tricky, come talk to me
- You should generally ignore archives (zip, tar), images (png, jpg), binaries (dmg, iso, exe), compiler output, log files, and .DS_Store (Mac)
- easy collaboration
- sync between machines
- off-site backup
- peer review
- Create new repository (visual instructions here: https://swcarpentry.github.io/git-novice/07-github/index.html)
- Call it “garden”
- Find HTTPS string that identifies repository
git remote add origin https://github.com/devnich/garden.git
git remote -v
git push origin master # you should get a password prompt
If you configure your origin as upstream, you can just do:
git push
git pull
pull
is a shortcut forfetch
+merge
git clone https://github.com/devnich/garden.git ~/Desktop/garden-clone
cd garden-clone
touch trees.txt
1. Plum 2. Pluot 3. Aprium
pwd # we are in ~/Desktop/garden-clone
git status
git add trees.txt
git commit -m "I like plums"
git push
cd ../garden # now we are in ~/Desktop/garden
ls
git pull
ls
1. Cherry tomatoes 2. Italian basil 3. Jalapenos 4. Scotch bonnet peppers
git add shopping_list.txt
git commit -m "Added more peppers our copy"
git push origin master
1. Cherry tomatoes 2. Italian basil 3. Jalapenos 4. Garlic
git add shopping_list.txt
git commit -m "Added garlic to rival copy"
# Rejected because Git can't merge changes cleanly
git push origin master
# Pulling results in a local conflict
git pull origin master
Edit the file to resolve the conflict. You can delete one of the two lines, combine them, or make any other changes. Delete the conflict markers before staging the file (the lines beginning in “<”, “=”, and “>”).
<<<<<<< HEAD 4. Garlic ======= 4. Cayenne peppers >>>>>>> dabb4c8c450e8475aee9b14b4383acc99f42af1d
You may want to enable a default merge tool:
git config --global merge.tool meld
- Open source merge tools include Vimdiff, Meld, Kdiff, Gitfiend, Git Cola, etc. There are many other options!
- Always pull before you push
- To minimize conflicts, do your work on a separate branch
- .ipynb files contain a lot of JSON boilerplate that isn’t code
- git blame: See who changed each line of a file
- git bisect: Find out when a change was introduced (good man page)
- git revert: Undo your recent commits (good man page)
- git add –patch: Stage a part of a file (“hunk”) instead the entire file
- git -i <command>: Run a command interactively, confirming each step
- git reset: Throw away uncommitted changes (there are many options that affect what gets thrown away; read the documentation)
- git reset –hard: Throw away some of your commits to get back to an earlier project state. Cannot be undone!
- git rebase: Rewrite the history of branch A to include branch B. This is different than merging branch B into branch A; merging retains your project history, whereas rebasing rewrites that history.
- git squash: Convert multiple commits into a single commit. This also rewrites your project history.
- git cherry-pick: Copy a single commit from a different branch. This rewrites your project history piecemeal, which can make it difficult to merge branches in the future.
- The Pro Git book: https://git-scm.com/book/en/v2
- Graphical user interfaces for Git (useful for visualizing diffs and merges): https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Graphical-Interfaces
- Git for Advanced Beginners: http://think-like-a-git.net
- “Git is built on a graph. Almost every Git command manipulates this graph. To understand Git deeply, focus on the properties of this graph, not workflows or commands.”: https://codewords.recurse.com/issues/two/git-from-the-inside-out
- A Visual Git Reference: https://marklodato.github.io/visual-git-guide/index-en.html