Goals
- Understand the differences between
git diff
andgit diff --staged
(orgit diff --cached
) - Understand the difference between
git reset
andgit reset --hard
- Use
git add -p
- Use
git checkout -p
- Note you can also rollback partial changes from the line gutter in RubyMine.
- Use
git rebase -i
- Understand what it means for pushing to a remote, and for working with your colleagues
- Use
git rebase --onto
. - What does
git commit --amend
do?- Understand what it means for pushing to a remote, and for working with your colleagues
- Understand the differences between
git pull
andgit pull --rebase
- Use
git revert <commit>
- What happens? Is the reverted code lost?
- Use
git cherry-pick <commit>
- Understand our cherry-picking workflow for production and why it is necessary
- Use
git reflog
- When is this useful?
- Find out how to check out a file from another branch
- Tip: Have a look at
git checkout --
andgit restore
- Tip: Have a look at
- Remember our recommended git workflow for feature branches
Resources
- Atlassian Advanced Git Tutorial Show archive.org snapshot
- git built-in help (
git help reflog
etc.) - Workflow for Splitting git Commits
- Howto: Write a proper git commit message
- Explanations for confusing git terminology Show archive.org snapshot
Exercises
While you are working on the movie DB as a single developer, real life applications are usually developed by entire teams. That means that local branches will frequently need to be rebased as they diverge from remote code. These exercises emulate such situations.
You are free to apply better naming conventions to the requested commit messages, they are only kept short here to fit inside the visualization.
Exercise 1: Split up the most recent commit
Head over to https://code.makandra.de/makandra/advanced-git-example-project and fork Show archive.org snapshot the repository to your private space. Ask your mentor to give you access to the repository.
Have a look at these branches and their commits:
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-documentation
commit id: "document-everything" type: HIGHLIGHT
Check out feature-documentation
of your fork and rewrite its history into multiple commits using git rebase
:
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-documentation
commit id: "README" type: HIGHLIGHT
commit id: "Setup" type: HIGHLIGHT
commit id: "Docs" type: HIGHLIGHT
The hash of the commit new-git-repo
should not change (785951a). Verify this by looking at git log --oneline
.
Exercise 2: Split up an earlier commit
Now imagine you are the author of the branch feature-binaries
.
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-binaries
commit id: "docs"
commit id: "add binaries" type: HIGHLIGHT
commit id: "init rails"
You are now asked to split up the add binaries
commit to one commit per binary.
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-binaries
commit id: "docs"
commit id: "echo binary" type: HIGHLIGHT
commit id: "curl binary" type: HIGHLIGHT
commit id: "init rails"
Exercise 3: Rebase onto a diverged feature branch with merge conflicts
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-node
commit id: "add NPM" type: HIGHLIGHT
branch feature-echo
checkout feature-node
commit id: "setup NVM" type: HIGHLIGHT
checkout feature-echo
commit id: "add echo script"
feature-echo
was branched of feature-node
while it only contained commit "add NPM". It added a new feature on it (add-echo-script).
In the meantime, feature-node
was code reviewed, squashed and force pushed. It now looks like this:
%%{init: { 'gitGraph': { 'mainBranchName': 'master'}} }%%
gitGraph:
commit id: "new-git-repo"
branch feature-node
commit id: "setup node" type: HIGHLIGHT
Rebase feature-echo
onto feature-node
so it has this history:
%%{init: { 'gitGraph': { 'mainBranchName': 'feature-echo'}} }%%
gitGraph:
commit id: "new-git-repo"
commit id: " " tag: "setup node" type: HIGHLIGHT
commit id: "add echo script"
The hash of the commit "setup node" should be identical within the two branches. Solve the resulting merge conflicts at the README so that the paragraph about the echo script comes after the introduction to Node.