refresher for SoftGroup staff
Wednesday, 12nd of October, 2016
git
- Distributed version control system
- Local, no server needed
- multiple backups
- fast operations
- works offline
- Branching model
- paradigm shift compared to CVS, SVN
- designed for multiple branches
- easy context switching
- enable a lot of workflows
git: (very) basic usage - 1
- Create a repository
matias@kashyyyk /tmp/training $ git init
Initialized empty Git repository in /tmp/training/.git/
- default branch is called 'master'
matias@kashyyyk /tmp/training $ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
- Status of a repository
git: (very) basic usage - 2
- Committing changes
- do the commit, select which files (all files: -a switch) + mandatory message
matias@kashyyyk /tmp/training $ git commit -a -m "first commit"
- (stage files to commit, if needed - e.g. for new files)
matias@kashyyyk /tmp/training $ git add .
- Write good commit messages ! Help here
NB:
git commits
(and git objects in general)
are identified
by SHA-1 hashes
commit c9f390172d109cf2bbc688648ca58796ef6f7c9
Use a graphical tool for commits !
- commit only parts of files
- synthetic view
- revert changes
git gui
git: (very) basic usage - 3
- Create a branch
matias@kashyyyk /tmp/training $ git checkout -b my_new_branch
Switched to a new branch 'my_new_branch'
- Switch to an existing branch
matias@kashyyyk /tmp/training $ git checkout master
Switched to a new branch 'master'
Use a graphical tool to look at your repository
- see commits, search
- see all branches (gitk --all)
- see changes (gitk specific_file for all changes to 1 file in particular)
gitk
Useful git commands - 1
- grep in all files of the repository
matias@kashyyyk ~/dev/mxcube3 $ git grep SampleChanger
mxcube3/__init__.py: import routes.Main, routes.Login, routes.Beamline, routes.Collection, routes.Mockups, routes.S
mxcube3/routes/Login.py: basket = int(sample_info["containerSampleChangerLocation"])
mxcube3/routes/Login.py: sample_info["containerSampleChangerLocation"] = "%d:%d" % (cell, puck)
mxcube3/routes/Sample.py: data = {generic_data, "SampleId":id, sample_data={'holderLength': 22.0, 'code': None, 'co
mxcube3/routes/Sample.py: data = {generic_data, "SampleId":id, sample_data={'holderLength': 22.0, 'code': None, 'co
mxcube3/routes/Sample.py: return_data={"SampleId":id, sample_data={'holderLength': 22.0, 'code': None, 'containerSa
mxcube3/ui/reducers/SamplesGrid.js: const limsLocation = `${sampleInfo.containerSampleChangerLocation} :
- reflog : shows information recorded when branch is updated
matias@kashyyyk ~/dev/mxcube3 $ git reflog
c9f3901 HEAD@{0}: checkout: moving from master to p
38aadf5 HEAD@{1}: checkout: moving from api to master
fe6d237 HEAD@{2}: checkout: moving from server_uistate to api
3c6289a HEAD@{3}: checkout: moving from master to server_uistate
38aadf5 HEAD@{4}: pull origin: Fast-forward
6abec15 HEAD@{5}: pull: Fast-forward
37301af HEAD@{6}: pull: Fast-forward
77c2377 HEAD@{7}: checkout: moving from redux_persist to master
helps recovering from (almost) any situation: lost commits recovery, undo...
Useful git commands - 2
- git log -S'something'
matias@kashyyyk ~/dev/mxcube3 $ git log -S'SampleGrid' --oneline
d11be99 Changed case of sample_grid to SampleGrid
f732dc8 Improved the way the grid size (width and number of columns) are calculated.
2ea69e2 Added the possibility to move sample items
- git diff: shows differences between 2 versions
matias@kashyyyk ~/dev/mxcube3 $ git diff master origin/refactoring -- ./mxcube3/__init__.py
diff --git a/mxcube3/__init__.py b/mxcube3/__init__.py
index 7c59ac2..2ee2393 100644
--- a/mxcube3/__init__.py
+++ b/mxcube3/__init__.py
@@ -1,15 +1,13 @@
from __future__ import absolute_import
from flask import Flask
-from flask import request
from flask.ext.socketio import SocketIO
from flask.ext.session import Session
search for commits adding or removing 'something'
... also works with 'gitk' :)
syntax: git diff branchA branchB -- path to file
Useful git commands - 3
- Reverting a file from an existing branch
matias@kashyyyk ~/dev/mxcube3 $ git checkout my_branch -- path to file
- cherry-pick: apply an existing commit to the current branch
Usage: applying a bug fix from a branch to another one, without getting all changes introduced by commits from this branch
matias@kashyyyk ~/dev/mxcube3 $ git cherry-pick a188350
Ready for more advanced stuff ?
A word about HEAD
- HEAD: pointer to the current commit of the current branch
matias@kashyyyk /tmp/training $ git reset --hard HEAD
command above removes all uncommitted changes (but it doesn't delete untracked files - see 'git clean' for this !)
advice: commit often, commit early to avoid uncommitted changes
you can squash your X latest commits into one using
'git rebase -i HEAD~X'
ACHTUNG: only for commits you didn't share with others yet, since it is rewriting the commits history
Stash
- git stash: puts all uncommitted changes in a safe place, and restores working tree to latest HEAD
- git stash list: displays stashes (cachettes)
- git stash pop: apply latest stash, and removes it
- git stash drop: discards latest stash
- git stash branch XXX: create a new branch XXX at the original commit when the stash has been done, apply stashed changes, and removes the stash
Submodules - 1
- Reference a git repository within another git repository
- The reference is a precise commit
Very convenient to guarantee the container project works, whatever happened to the submodule
Similar to subversion's Externals, in a way
- as a consequence, a submodule doesn't follow its parent code automatically : this is what is causing so much trouble to newcomers
When the submodule is initialized, it is in "detached HEAD" state: the HEAD is not in a branch
Submodules - 2
matias@brian /tmp/training $ tree
.
├── HelloC
│ └── hello.c
└── HelloPython
└── hello.py
1. Two git repositories, HelloC and HelloPython
matias@brian /tmp/training $ mkdir Hello; cd Hello; git init
Initialized empty Git repository in /tmp/submodules/Hello/.git/
2. Let's create a new Hello git repository
3. Add the submodules
matias@brian /tmp/submodules/Hello $ git submodule add ../HelloC
Cloning into 'HelloC'...
done.
matias@brian /tmp/submodules/Hello $ git submodule add ../HelloPython
Cloning into 'HelloPython'...
done.
matias@brian /tmp/submodules/Hello $ tree
.
├── HelloC
│ └── hello.c
└── HelloPython
└── hello.py
2 directories, 2 files
git commit -a -m "added submodules"
[master (root-commit) 4b1bc96] added submodules
3 files changed, 8 insertions(+)
create mode 100644 .gitmodules
create mode 160000 HelloC
create mode 160000 HelloPython
4. Commit the submodule update
Done !
Collaborating using remotes
- Distributed nature of git
- remote repositories are versions of your project located elsewhere
- can be on the internet, over a private network, or on disk
- code can be pushed to or pulled from a remote
- For BCU, first remote for your project is on gitlab (or github in case of external collaboration)
- first remote is often called 'origin'
- this is where the code originally comes from
- ... but it is just a name, remotes can be called anything
- The remote URL is useful to clone a repository
- git clone : make a local copy of a remote repository
git remote
- Showing remotes
- Adding a remote
matias@brian ~/dev/mxcube3 $ git remote -v
matias git@github.com:mguijarr/mxcube3 (fetch)
matias git@github.com:mguijarr/mxcube3 (push)
origin git@github.com:mxcube/mxcube3 (fetch)
origin git@github.com:mxcube/mxcube3 (push)
matias@brian ~/dev/mxcube3 $ git remote add marcus git://github.com/marcus-oscarsson/mxcube3
matias@brian ~/dev/mxcube3 $ git remote -v
marcus git://github.com/marcus-oscarsson/mxcube3 (fetch)
marcus git://github.com/marcus-oscarsson/mxcube3 (push)
matias git@github.com:mguijarr/mxcube3 (fetch)
matias git@github.com:mguijarr/mxcube3 (push)
origin git@github.com:mxcube/mxcube3 (fetch)
origin git@github.com:mxcube/mxcube3 (push)
git fetch
- Downloading changes from a remote repository
matias@brian ~/dev/mxcube3 $ git fetch marcus
remote: Counting objects: 430, done.
remote: Compressing objects: 100% (146/146), done.
remote: Total 430 (delta 329), reused 233 (delta 233), pack-reused 51
Receiving objects: 100% (430/430), 84.30 KiB | 0 bytes/s, done.
Resolving deltas: 100% (332/332), completed with 91 local objects.
From git://github.com/marcus-oscarsson/mxcube3
* [new branch] api -> marcus/api
* [new branch] master -> marcus/master
* [new branch] prototype -> marcus/prototype
* [new branch] queue-api -> marcus/queue-api
* [new branch] sample-queue-id -> marcus/sample-queue-id
* [new branch] samplegrid-queue -> marcus/samplegrid-queue
* [new branch] serformat -> marcus/serformat
* [new branch] serialization -> marcus/serialization
Remote branches - 1
- Getting list of all branches (locales and remotes)
matias@brian ~/dev/mxcube3 $ git branch -ra
*master
redux_persist
server_uistate
remotes/marcus/api
remotes/marcus/master
remotes/marcus/prototype
remotes/marcus/queue-api
remotes/marcus/sample-queue-id
remotes/marcus/samplegrid-queue
remotes/marcus/serformat
remotes/marcus/serialization
remotes/matias/master
remotes/origin/master
remotes/origin/mxcube-temporary
remotes/origin/redux_persist
remotes/origin/refactoring
- Duplicating a remote branch for local use
matias@brian ~/dev/mxcube3 $ git checkout -b copy_of_marcus_api marcus/api
Branch copy_of_marcus_api set up to track remote branch api from marcus.
Switched to a new branch 'copy_of_marcus_api'
Remote branches - 2
- Pushing
matias@brian ~/dev/mxcube3 $ git push origin master
- Pulling
matias@brian ~/dev/mxcube3 $ git pull
"push the commits from local branch to the origin remote, in the master branch"
'git pull' does a 'git fetch' + a 'git merge'
If remote branch tracking is enabled, it automatically merges the remote branch into the local one
git merge
git rebase
- much cleaner project history (no merge commits)
- perfectly linear project history—you can follow the tip of feature all the way to the beginning of the project without any forks
- easier to navigate with commands like git log, git bisect, and gitk
We prefer rebase vs merge
BUT beware: NEVER rebase a public branch !
Configure 'git pull' to do rebase instead of merge
git config --global pull.rebase true
Our git workflow
- Feature branch workflow
- stable master branch
- new features in branches
- merge requests (with gitlab)
- Many advantages
- in theory, master should not contain broken code
- facilitates Continuous Integration
- several developers can work on a new feature without disturbing the main codebase
- communication++ between developers, code review
Merge request
- Feature branch workflow
- only 1 public repository
- pushed branches have to be merged
- source for merge request will always be from a feature branch
- destination will always be 'master' branch
Git training for BCU
By Matias Guijarro
Git training for BCU
Git refresher for BCU
- 1,364