Lecture 07 - More Git Commands, CLI and Git Practice
push and pull changes to and from remote repositories.gitignore to avoid tracking certain filesgit branch and git checkoutclone and fork repositoriesgit checkout and git resetmaster/mainSource: Lodato (2010)
Today we will cover:
git diffgit commit --amendgit cherry-pick 😅git rebase and its usesgit stashgit diff?git diff shows what has changed, line by linemy-project and look at itReading the output:
a/ is the old version, b/ is the new oneindex e69de29..42b9fb1: short IDs of the file before and after the change; 100644 means a regular file (other file modes)@@ -0,0 +1 @@: old file had 0 lines, new file has 1 line starting at line 1+ before a line: added; - before a line: removedgit diff commandsBasic diff commands:
git diff: shows unstaged changes in working directorygit diff --staged: shows staged changes ready to commitgit diff HEAD: shows all changes since last commitgit diff --name-only: shows only filenames that changedComparing commits:
git diff commit1..commit2: compares two specific commitsgit diff branch1..branch2: compares two branchesgit diff --stat: shows summary of changes (files modified, insertions, deletions)@@ -1,4 +1,4 @@ means that in the original file, lines 1 to 4 were present, and in the new file, lines 1 to 4 are also present, but with some changesgit commit --amend?Amending the commit message:
Adding forgotten files:
Both together:
Important rules:
git revert, which adds a new commit that reverses itgit resetgit reset can move the HEAD pointer to a previous commit--soft keeps your changes staged--mixed (the default) keeps them, but unstaged. This is usually what you want, so you can review the files before committing again--hard throws them away entirelyUndo last commit, keep changes staged:
Undo last commit, keep changes unstaged:
Undo last commit and discard changes:
HEAD~, such as HEAD~2 for the last two commitsgit cherry-pick?git cherry-pick allows you to pick specific commits from one branch and apply them to anothergit cherry-pickBasic cherry-pick:
After cherry-picking:
Handling conflicts:
Common use cases:
git rebasegit rebase allows you to move or combine commits to a new base commitInteractive rebase:
Rebase onto another branch:
During interactive rebase you can:
pick: use the commit as-isreword: change the commit messageedit: modify the commit contentssquash: combine with the previous commitdrop: remove the commit entirelygit stash?git stash puts your uncommitted changes aside, leaving a clean working directory. This is very useful!Use it when:
pull but have local changes in the way# 1. On feature-branch, you edit a tracked file
echo "df = df.dropna()" >> 01-data-cleaning.py
git status # modified: 01-data-cleaning.py
# 2. A bug report arrives. Park your edit
git stash
git status # nothing to commit, working tree clean
# 3. Fix the bug on main
git checkout main
echo "# Fixed typo" >> README.md
git commit -am "Fix typo in README"
# 4. Go back and pick up where you left off
git checkout feature-branch
git stash pop # your dropna() line is backgit stash commandsSaving and restoring stashes:
# Stash current changes (tracked files only)
git stash
# Stash with a descriptive message
git stash push -m "WIP: adding user authentication"
# Stash including untracked files
git stash -u
# Stash including untracked and ignored files
git stash -a
# Restore most recent stash and remove from stack
git stash pop
# Restore most recent stash but keep in stack
git stash applyManaging multiple stashes:
# List all stashes
git stash list
# Apply a specific stash
git stash apply stash@{2}
# Drop a specific stash
git stash drop stash@{1}
# Clear all stashes (use with caution!)
git stash clear
# Show changes in most recent stash
git stash show
# Show changes in stash with diff
git stash show -p stash@{0}git stashA very common scenario:
You’ve been coding away, only to realise you’re on the wrong branch! 😱
git stash makes it easy to move your uncommitted changes to the correct branch:
This technique works for both tracked and untracked files (use git stash -u for untracked).
Creating a new branch from stash:
If the branch doesn’t exist yet, you can create it directly from the stash:
This command:
Pro tip: This is the safest way to recover stashed work if you’re unsure about conflicts!
gh and logged in during lecture 06. Let’s check bothbrew install gh. WSL: Linux instructionsgh auth login (next slide)Repository operations:
Pull requests and issues:
# Create a new pull request
gh pr create --title "My PR" --body "Description of my PR"
# List pull requests
gh pr list
# View pull request details
gh pr view 123 --web
# Create a new issue
gh issue create --title "My Issue" --body "Description of my issue"
# List issues
gh issue list
# View issue details
gh issue view 456 --webSet up the repository
git-practice directory, move into it, and initialise a repositorysrc folder, then use brace expansion to create main.py, utils.py and test.py inside it in one commandecho to write print("Hello") into src/main.py, and check its contents with cat. Commit everything: “Initial commit”Check and fix
echo to replace the text with print("Hello, world"), then run git diff. Commit with the message “Updte greeting”, then fix the typo with --amendsrc/test.py to src/test_main.py, check with ls src, and commit: “Rename test file”Branches and stash
hotfix. Add a .gitignore containing temp/ and commit: “Add gitignore”git log hotfix --oneline to find the ID of the “Add gitignore” commit, then bring over only that commit with cherry-pick# TODO to src/utils.py, stash the change, and check that git status is cleangit stash pop, then use cat to confirm # TODO is thereTo GitHub
Check your work with git log --oneline and git status. Answers are in the appendix at the end of this lecture
Here are the answers to the practice quiz. Try to complete the quiz first before checking these answers!
mkdir git-practice && cd git-practice && git initmkdir src && touch src/{main,utils,test}.pyecho 'print("Hello")' > src/main.py && cat src/main.py && git add . && git commit -m "Initial commit"echo 'print("Hello, world")' > src/main.py && git diff, then git commit -am "Updte greeting" and git commit --amend -m "Update greeting"mv src/test.py src/test_main.py && ls src && git add . && git commit -m "Rename test file"
git mv src/test.py src/test_main.py does the same and stages it in one stepgit checkout -b hotfix && echo "temp/" > .gitignore && git add .gitignore && git commit -m "Add gitignore"git checkout main && git log hotfix --oneline, then git cherry-pick <commit-id>
git init gave you a branch called master, use that name instead. Check with git branchecho "# TODO" >> src/utils.py && git stash && git statusgit stash pop && cat src/utils.pygh repo create git-practice --private --source=. --push && gh repo view --web