Skip to content
Snippets Groups Projects
Verified Commit dde376cf authored by Laurent Heirendt's avatar Laurent Heirendt :airplane:
Browse files

add advanced slides

parent f4eaee68
No related branches found
No related tags found
No related merge requests found
# Rebase
# Cherry-pick
# Conflict resolution
\ No newline at end of file
# Amend a commit
* Enables to change a commit on `HEAD` (the last commit)
* Start by creating and committing a file in the `attendees` directory:
```bash
$ cd attendees
$ echo "# Firstname Lastname" > myName.md
$ git add myName.md
$ git commit -m "Add firstname lastname to attendees"
```
* Check the commit in the `log`:
```bash
$ git log
```
# Example 1: change the commit message
* Verify that your staging area is clear:
```bash
$ git status
```
* Use `git commit --amend` to change the commit
* Alternatively, you can use the `-m` flag to edit only the commit message:
```bash
$ git commit --amend -m "Add title"
```
* Check the commit message in the `log`:
```bash
$ git log
```
# Example 2: change the commit content
* In your editor, change the text in the `myName.md` file. For instance:
```bash
My biography ...
```
* You can see that the file changed:
```bash
$ git status
```
* With the changes staged use the following command to commit the changes into the previous commit:
```bash
$ git add myName.md
$ git commit --amend --no-edit
```
* Check the commit content:
```bash
$ git show HEAD
```
* This will create and commit a new commit with the staged changes added and the same commit message.
# Cherry-picking
* Cherry-picking allows to pick one (or more) specific commits from a list of commits.
* Only the chosen commit(s) are picked, not everything up to that commit.
<div style="top: 8em; left: 25%; position: absolute;">
<img src="slides/img/cherryPick.png" height=500px>
</div>
# Example (1)
* Create and commit two files in the `develop ` branch
```bash
$ git checkout develop
$ echo "# Venue details" > location.md
$ # add and commit the file location.md
$ echo "# Speakers" > speakers.md
$ # add and commit the file speakers.md
```
# Example (2)
* Check the `log` and note down the `SHA1` of the commits you want to cherry-pick. Then:
```bash
$ git checkout myBranch
$ git cherry-pick <SHA1>
```
* Check the log again and see if the changes were applied correctly. Note the new SHA1!
```bash
$ git show <newSHA1>
```
* Repeat for the second commit
* Push the changes to `myBranch`
```bash
$ git push origin myBranch
```
* Note that the `-f` flag is not needed to force push (no history has been rewritten)
# Partial chery-picking
* Partial cherry-picking allows you to unpack the changes from a commit.
* Imagine you committed many files, and you want to remove certain files.
* In practice:
- You commited all files, and you realize that there is your data inside!
- You have committed accidentally sensitive data, such as your password
- You committed hidden files, for instance `.DS_Store` files
- ...
# Example (1)
* Hard reset the `myBranch` branch:
```bash
$ git checkout myBranch
$ git reset --hard HEAD~2 # do not preserve files
```
* Reset the `develop` branch:
```bash
$ git checkout develop
$ git reset HEAD~2 # preserve files
```
* Add the `location.md` and the `speakers.md` files as 1 commit:
```bash
$ git add location.md speakers.md
$ git commit -m "add location and speakers files"
```
# Example (2)
Cherry-pick the commit from `develop` over to `myBranch`:
```bash
$ git checkout myBranch
$ git cherry-pick -n <SHA1>
$ git status
```
Now, remove the file `location.md`:
```bash
$ git restore --staged location.md # old version of git: $ git reset HEAD location.md
$ rm location.md
```
Commit the changes:
```bash
$ git commit -m "add speakers file"
```
# Conflict resolution
* A conflict occurs when two changes change the same line in a file
* Some conflict may be resolved automatically, but major conflicts
always need to be resolved manually
* Tools exist to streamline conflict resolutions, we use `kdiff3`
* Conflicts can happen during `merge`, `cherry-pick`, and `rebase`
# Example 1: Conflict resolution when locally merging (1)
* Checkout the branch `myNewBranch` and change the file `template.md`:
```bash
$ git checkout myNewBranch
```
* Use your favorite editor and type:
```bash
# Advanced git training course
## Firstname Lastname
```
* Add and commit that change.
* Checkout the branch `myBranch` and change the file `template.md`:
```bash
# Advanced git training -- Course
## Firstname Lastname
```
* Then, save, add, and commit that change.
# Example 1: Conflict resolution when locally merging (2)
* Merge the `myNewBranch` into the `myBranch` branch:
```bash
$ git merge myNewBranch
```
* A conflict appears:
```bash
$ git merge myNewBranch
Auto-merging attendees/template.md
CONFLICT (content): Merge conflict in attendees/template.md
Automatic merge failed; fix conflicts and then commit the result.
```
* Start the merge tool:
```
$ git mergetool
```
# Example 1: Conflict resolution when locally merging (3)
* This opens kdiff3 if it was properly set up. There are 3 versions:
- **A**: version on `myBranch` before the recent change.
- **B**: version on `myNewBranch`
- **C**: version on `myBranch` after the recent change
* Resolve the conflict and save. Then:
```bash
$ git merge --continue
```
* If you check the status, you will find a `.orig` file. This is a backup and contains the conflict.
```bash
$ git status
$ cat template.md.orig
```
* If you do not need anymore the backup file, you can remove it.
* You can either `rm` the `.orig` file, or you can use `git clean -fdx`. **Tip:** use `--dry-run` first to list all files that would be deleted.
# Example 2: Conflict resolution when cherry-picking (1)
If you follwed **Example 1**, reset the `myBranch` branch:
```
$ git checkout myBranch
$ git reset --hard HEAD~1
```
Get the SHA1 of the commit on the `myNewBranch` branch:
```bash
$ git show myNewBranch HEAD
```
Then, cherry-pick that commit:
```bash
$ git cherry-pick <SHA1>
```
# Example 2: Conflict resolution when cherry-picking (2)
You will get a message that there is a conflict:
```
error: could not apply e3ffc09... edit content of template
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
```
* Start the merge tool as before:
```
$ git mergetool
```
* Resolve the conflict and save. Then:
```bash
$ git cherry-pick --continue
```
The remaining steps are the same as explained in **Example 1**.
\ No newline at end of file
......@@ -8,6 +8,12 @@
{ "filename": "essential_commands.md" },
{ "filename": "syncFork.md" },
{ "filename": "best_practices.md" },
{ "filename": "advanced.md" },
{ "filename": "amend.md" },
{ "filename": "reset.md" },
{ "filename": "revert.md" },
{ "filename": "rebase.md" },
{ "filename": "chPick.md" },
{ "filename": "merge.md" },
{ "filename": "conflict.md" },
{ "filename": "thanks.md" }
]
\ No newline at end of file
# Merging branches locally
* Merge a branch into another one locally
* Combines all the commits from a source branch onto a target branch
* In practice, this is very useful if you 'just want to try out something', or 'draft' something
# Example (1)
* Create a new branch from your `myBranch` branch:
```bash
$ git checkout myBranch
$ git checkout -b myNewBranch
```
* Add two files to the `myNewBranch` branch in two separate commits:
```bash
$ echo "# Trevor Westman" > trevor.md
$ # add and commit the file trevor.md
$ echo "# Gustav Bergen" > gustav.md
$ # add and commit the file gustav.md
```
# Example (2)
* Check the `log` of the `myNewBranch` and `myBranch` branches:
```bash
$ git log myBranch
$ git log myNewBranch
```
* Go to `myBranch` and merge the `myNewBranch` branch into it
```bash
$ git checkout myBranch
$ git merge myNewBranch
$ git log myBranch
```
# Rebasing (1)
* `git rebase` enables to shift forward your commits in time
* Move/combine a sequence of commits to a new base commit
* Avoid discrepancies when multiple people work on the same project
* Linear git history (no merge commits)
* Rebasing is like saying, “I want to base my changes on what everybody has already done.”
Imagine the following situation:
<div style="top: 14em; left: 25%; position: absolute;">
<img src="slides/img/beforeRebase.png" height="500px">
</div>
* There are commits on `develop` that aren't in `myBranch`.
# Rebasing (2)
* After rebase, the commits in the `myBranch` branch will be place on top of `develop`.
<div style="top: 5em; left: 25%; position: absolute;">
<img src="slides/img/afterRebase.png" height="500px">
</div>
# Example (1):
* A merge request against `develop` is still open. **Repository maintainer: review, and merge it.**
* Create a file in your branch `myBranch`
```bash
$ git checkout myBranch # if necessary
$ echo "# List of attendees" > list.md
$ # add and commit the file
```
* Then, update your `develop` branch from the `upstream` remote:
```bash
$ git fetch upstream
$ git checkout develop
$ git merge upstream/develop
$ git checkout myBranch
```
* Check the histories of both branches
```bash
$ git log
```
# Example (2):
* Rebase `myBranch` on top of the updated `develop`:
```bash
$ git checkout myBranch
$ git rebase develop
```
* Check the history of your branch again
```bash
$ git log
```
* If you pushed previously your branch `myBranch`, you need to rewrite its history remotely - you need to **force push**.
# Interactive Rebasing - flag `-i`
* An interactive rebase is performed with the `-i` flag:
```bash
git rebase -i <branch>
```
* Enables more precise control over the rebased commits
* Before committing many actions are available
```bash
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
```
# Example 1: Reword and fixup (1)
* Switch to your own branch `myBranch`
* Add and commit two files to this branch:
```bash
$ # git checkout myBranch && cd attendees
$ echo "# William Odell" > william.md
$ # add and commit the file william.md with the message 'add william to attendee list'
$ echo "# Roberta Ross" > roberta.md
$ # add and commit the file roberta.md with the message 'add roberta to attendee list'
$ git push origin myBranch
```
Now, we want to:
- Reword the first commit's message to: `Add William and Roberta to attendee list`
- Combine the second and first commit into one
- Omit the commit message of the second commit.
# Example 1: Reword and fixup (2)
* Perform an interactive rebase with the two last commits:
```bash
$ git rebase -i HEAD~2
```
* The dialog shows up (example):
```bash
$ pick 1234567 add william to attendee list
$ pick abcdef0 add roberta to attendee list
```
* The keywords `pick` can now be changed to `reword` and `fixup` respectively:
```bash
$ reword 1234567 add william to attendee list
$ fixup abcdef0 add roberta to attendee list
```
* Edit by typing `i`
* Change the message of commit `1234567` to `Add William and Roberta to the attendee list`
* Save with `:wq`
# Example 2: Pick and squash (2)
* If you want to **keep** both commit messages in one commit, change the action to `squash`
```bash
$ pick 1234567 add william to attendee list
$ squash abcdef0 add roberta to attendee list
```
* This will create a commit with both modified files, with the commit message being a combination of the two commit messages.
* Push the changes to `myBranch` with `-f`:
```bash
$ git push origin myBranch -f
```
\ No newline at end of file
# Reset a branch
* Enables to reset a branch back to a previous commit
* Discards ALL commits made after the selected commit HEAD
* This happens often in **practice**:
you pushed to a branch, then realize that you made a mistake in the commit, and want to start over.
# Example: Hard reset of a branch (1)
* Start by committing two files:
```bash
# commit first file ...
$ echo "# CV of Firstname Lastname" > myCV.md
$ git add myCV.md
$ git commit -m "add cv for Firstname Lastname"
# commit second file ...
$ echo "# Biography of Firstname Lastname" > myBio.md
$ git add myBio.md
$ git commit -m "add biography for Firstname Lastname"
$ git push origin myBranch
```
* Check the commits, copy the `SHA1` of the **second last** commit:
```bash
$ git log
```
# Example: Hard reset of a branch (2)
* Use the `reset --hard` command in order to undo the commit with `<SHA1>`:
```bash
$ git reset --hard <SHA1>
```
* Check what happened in the log
* Force push your branch (overwrite the history) with `-f`:
```bash
$ git push origin myBranch -f
```
# Notes
* Alternatively, you can also remove the last commit:
```bash
$ git reset --hard HEAD~1
```
* With a `--hard` reset, the index and the working tree are reset.
* If you omit the `--hard` flag, a mixed reset is made. This resets the index, but not the working tree
```bash
$ git reset HEAD~1
```
\ No newline at end of file
# Reverting a commit
* Enables the deletion of committed commits by reverting the changes.
* A trace is kept in history of the original commit and the reverted one.
# Example:
* On your branch, create and commit a file:
```bash
$ echo "# Grades for Firstname Lastname" > grades.md
$ git add grades.md
$ git commit -m "File with grades for Firstname Lastname"
```
* Note down the `SHA1` by checking the `log`
* Use the `git revert` command to undo that commit:
```bash
$ git revert <SHA1>
```
* This will open a dialog (`vim`-like editor). Exit with `:wq`
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment