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

Merge branch 'advancedtraining-siu' into 'develop'

Draft of slides for advanced training (SIU)

See merge request !52
parents 8c5f39b9 608f70dd
No related branches found
No related tags found
No related merge requests found
Showing
with 674 additions and 0 deletions
# 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
# Getting Started
* Fork and then clone the tutorial repository
<a href="https://github.com/LCSB-BioCore/advanced-git-practice">https://github.com/LCSB-BioCore/advanced-git-practice</a>
```bash
$ git clone git@github.com:<first.last>/advanced-git-practice.git
```
* Add a remote `upstream`
```bash
$ cd advanced-git-practice
# add upstream URL
$ git remote add upstream git@github.com:<first.last>/advanced-git-practice.git
$ git fetch upstream
```
* Check the remotes with:
```bash
$ git remote -v
```
* Create the `develop` branch and your own branch `myBranch` based on the `develop` branch from `upstream` using the `-b` flag
```bash
$ git checkout -b develop upstream/develop
$ git checkout -b myBranch
```
\ No newline at end of file
# Ignore files
In the file `.gitignore`, all untracked files that should be ignored by `git` are listed:
```
.DS_Store
data
*.csv
```
If you want to exclude certain files from this list:
```
!*.yml
config/*.yml
```
This tracks changes in all yml file, but not in the `config` folder.
Examples: www.gitignore.io
\ No newline at end of file
../../2019-09-24_advancedGitTraining/slides/img
\ No newline at end of file
# Advanced Git Training - SIU
## October 10, 2019
<div style="top: 6em; left: 0%; position: absolute;">
<img src="theme/img/lcsb_bg.png">
</div>
<div style="top: 5em; left: 60%; position: absolute;">
<img src="slides/img/r3-training-logo.png" height="200px">
<br><br><br>
<h1>Advanced Git Concepts</h1>
<br><br><br>
<h2>
Laurent Heirendt, PhD<br><br>
laurent.heirendt@uni.lu<br><br>
<i>Luxembourg Centre for Systems Biomedicine</i>
</h2>
</div>
[
{ "filename": "index.md" },
{ "filename": "overview.md" },
{ "filename": "gettingStarted.md" },
{ "filename": "ignore.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" }
]
# 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
```
# Overview
1. Installation and getting started
2. Amend last commit
3. Resetting to a previous commit
4. Reverting commits
5. Rebasing in Git
6. Git cherry-picking
7. Merging branches
8. Conflict Resolution
# 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
# Thank you.
<center><img src="slides/img/r3-training-logo.png" height="200px"></center>
Contact us if you need help:
<a href="mailto:r3lab.core@uni.lu">r3lab.core@uni.lu</a>
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