The GIT version-control system#
Most of the documention find here is inspired or copied from the excellent ressources provided by the CodeRefinery project (Here an example of such workshop in Uppsala december 2018). CodeRefinery is a project within the Nordic e-Infrastructure Collaboration (NeIC). NeIC is an organisational unit under NordForsk.
Basics#
Command | Comment |
---|---|
git init | initialize new repository |
git add | add files or stage file(s) |
git commit | commit staged file(s) |
git status | see what is going on |
git log | see history |
git log --oneline | to get a better log of your commits history |
git diff | show unstaged/uncommitted modifications |
git show | show the change for a specific commit |
git mv | move tracked files |
git rm | remove tracked files |
Undoing things#
Command | Comment |
---|---|
git revert f960dd3 | This creates a new commit that does the opposite of the reverted commit. The old commit remains in the history |
git commit --amend | Amend to the last commit. This can also be used to modify the last commit message. Note that this will change the commit hash. This command modifies the history. This means that we never use this command on commits that we have shared with others. |
git checkout \<filename> | Undo unstaged/uncommitted changes. |
The staging area#
The staging area helps us to create well-defined commits.
Command | Comment |
---|---|
git diff | show unstaged/uncommitted modifications |
git diff --staged | see staged changes |
git reset | unstages staged changes |
git checkout \<path> | check out the latest staged version ( or committed version if file has not been staged ) |
git add -u | stage all modification |
Aliases#
Command | Comment |
---|---|
git config --global alias.graph "log --all --graph --decorate --oneline" | the command "log --all --graph --decorate --oneline" can now be called using git graph |
Branching and merging#
Command | Comment |
---|---|
git branch | see where we are |
git branch \<name> | create branch \<name> |
git checkout \<name> | switch to branch \<name> |
git merge \<name> | merge branch \<name> (to current branch) |
git branch -d \<name> | delete branch \<name> |
git branch -D \<name> | delete unmerged branch |
git checkout -b \<name> | create branch \<name> and switch to it |
git reset --hard \<branch/hash> | rewind current branch to \<branch/hash> and throw away all later code changes |
git reset --soft \<branch/hash> | rewind current branch to \<branch/hash> but keep all later code changes and stage them |
git rebase \<branch/hash> | cut current branch off and transplant it on top of \<branch/hash> |
git reflog | show me a log of past hashes I have visited |
git checkout -b \<branch/hash> | create a branch pointing to <bran |
- Typical workflows
With this there are two typical workflows:
$ git checkout -b new-feature # create branch, switch to it
$ git commit # work, work, work, ...
# test
# feature is ready
$ git checkout master # switch to master
$ git merge new-feature # merge work to master
$ git branch -d new-feature # remove branch
Sometimes you have a wild idea which does not work. Or you want some throw-away branch for debugging:
$ git checkout -b wild-idea
# work, work, work, ...
# realize it was a bad idea
$ git checkout master
$ git branch -D wild-idea # it is gone, off to a new idea
# -D because we never merged back
No problem: we worked on a branch, branch is deleted, master is clean.
Rebase vs. merge Git rebase and commit squashing
Tagging#
Command | Comment |
---|---|
git tag -a v1.0 -m "message" | To record particular states or milestones of a project at a given point in time, like for instance versions. |
git push origin \<tagname> | To push a tag to remote servers. |
git push --delete origin \<tagname> | To delete the remote tag. |
git tag --delete \<tagname> | To delete the local tag. |
Conflict resolution#
See the link for manual resolution.
Command | Comment |
---|---|
git merge -s recursive -Xours branch-name | merge and in doubt take the changes from current branch |
git merge -s recursive -Xtheirs branch-name | merge and in doubt take the changes from less-avocados branch |
git merge --abort | Abort a conflicting merge |
Interrupted work#
You are in a middle of a development and a colleague wants to fix/commit something right now. How to do ? * Stashing The stash is the first and easiest place to temporarily “stash” things. The stashes form a stack, so you can stash several batches of modifications.
Command | Comment |
---|---|
git stash | will put working directory and staging area changes away. Your code will be same as last commit. |
git stash pop | will return to the state you were before. Can give it a list. |
git stash list | will list the current stashes. |
git stash save NAME | is like the first, but will give it a name. Useful if it might last a while. |
git stash save [-p] [filename] | will stash certain files files and/or by patches. |
git stash drop | will drop the most recent stash (or whichever stash you give). |
git stash apply | reapply the work from the most recent stash |
git stash apply stash@{2} | reapply the work from a specific stash |
- Create branches
git checkout -b temporary # create a branch and switch to it git add <paths> # stage changes git commit # commit them git checkout master # back to master # do your work... git checkout temporary # continue where you left off
Working with remotes#
Command | Comment |
---|---|
git clone https://host.com/user/project.git project | cloning a repository |
git push origin master | push the change to the upstream repository |
git pull origin master | Pull updates from the upstream repository (It is equivalent to git fetch origin + git merge origin/master ) |
git pull --rebase origin master | alternative to avoid merge commits |
git push origin -u branchName | Push your change as a new branch branchName |
git push origin somefeature | push to the remote branch somefeature |
git pull origin somefeature | pull to the remote branch somefeature |
git push origin --delete somefeature | delete the remote branch somefeature |
Git archaeology#
Command | Comment |
---|---|
git diff HEAD^^ HEAD \<filename> | to see the difference for a file \<filename> between now and two commits back |
git diff 61a86561a1edb438963f5f22ec9e0773a0c4aacf HEAD \<filename> | to see the difference for a file \<filename> between now and a specific commit |
git show e83c51633 | Inspecting commit e83c51633 |
git grep -i term | Greps entire repository below current directory |
git blame \<filename> | Show what revision and author last modified each line of a file. |
git log --oneline --grep "term" | grepping commit messages |
git log -S 'term' \<filename> | Finding removed code (term) from file \<filename> |
git checkout -b \<name> \<hash> | Branch from arbitrary (earlier) hash. Recommended mechanism to inspect old code. remove the |
git shortlog --summary --numbered | To show all users and the number of commits |
- bisect
$ git bisect start $ git bisect good 89578ed # this is a commit that worked $ git bisect bad HEAD # last commit is broken # now compile and/or run # after that decide whether $ git bisect good # or $ git bisect bad # now compile and/or run # after that decide whether $ git bisect good # or $ git bisect bad # iterate until commit is found
This can even be automatized with git bisect run <script>
. For this you write a script that returns zero/non-zero (success/failure).
Cherry Picking#
When?
Let’s say you are working in an project where you are making changes in a branch called new-features
. You have already made a few commits but want to move just one of them into the master branch.
How?
* Checkout the branch where you want to cherry pick the specific commits (git checkout branchName
) * Cherry pick from new-features branch
(git cherry-pick __commit-id__
)
Command | Comment |
---|---|
git cherry-pick commit-hash | cherry pick the commit with hash commit-hash |
git cherry-pick commit-hash1 commit-hash2 | cherry pick several commits |
git cherry-pick --continue | When the cherry picking stoped by a conflicts and you have resolved it, then launch this command |
git cherry-pick --abort | Cancel the operation and return to the pre-sequence state |
git cherry-pick -m 1 \<hash> | herry pick a merge instead of a commit |
/!\ Cherry picking is commonly discouraged in developer community. The main reason is because it creates a duplicate commit with the same changes and you lose the ability to track the history of the original commit. If you can merge, then you should use that instead of cherry picking. Use it with caution!