2. From SVN to Git
Martin Malek GIT Basics 2016 2 / 67
3. SVN Features
Centralized version control system
Commit as atomic operation
Versioning maintained for directories and file metadata
Client/Server protocol sends diffs
Cons
Renaming of files causes loss of the history
Lack of management tools (e.g. deleting part of the history)
Vulnerable to corruption
Martin Malek GIT Basics 2016 3 / 67
4. Git features
Distributed version control system
Strong support for non-linear development (branches and merges)
Efficient handling of large projects (e.g. Linux kernel)
Pluggable merge strategies
Git doesn’t delete data, only adds
Cons
More disk space required
No native client for Windows
Martin Malek GIT Basics 2016 4 / 67
5. Centralized vs. Distributed version control
Centralized VCS systems are designed with the intent that there is
One True Source that is Blessed, and therefore Good. All developers
work (checkout) from that source, and then add (commit) their
changes, which then become similarly Blessed.
Distributed VCS systems are designed with the intent that one
repository is as good as any other, and that merges from one
repository to another are just another form of communication. Any
semantic value as to which repository should be trusted is imposed
from the outside by process, not by the software itself.
The real choice between using one type or the other is organizational -
if your project or organization wants centralized control, then a DVCS
is a non-starter. If your developers are expected to work all over the
country/ world, without secure broadband connections to a central
repository, then DVCS is probably your salvation.
Martin Malek GIT Basics 2016 5 / 67
12. Configuration
Git has global and project configuration
To change configuration, you can run
git config <key> <value>
git config --global <key> <value>
Same goes for .gitignore. It’s good practice to have global gitignore
with files for your IDE etc.
Martin Malek GIT Basics 2016 12 / 67
13. Line endings
When you view changes in a file, Git handles line endings in its own way.
git config --global core.autocrlf true
Martin Malek GIT Basics 2016 13 / 67
14. Optionally, you can configure the way Git manages line endings on a
per-repository basis by configuring a special .gitattributes file.
The .gitattributes file must be created in the root of the repository
and committed like any other file.
# in case people don't have core.autocrlf set.
* text=auto
# declare text files you want to always be normalized and converte
# to native line endings on checkout.
*.c text
# Declare files that will always have CRLF line endings on checkou
*.sln text eol=crlf
# Denote all files that are truly binary and should not be modifie
*.png binary
Martin Malek GIT Basics 2016 14 / 67
15. text=auto
Git will handle the files in whatever way it thinks is best. This is
a good default option.
text eol=crlf
Git will always convert line endings to CRLF on checkout. You
should use this for files that must keep CRLF endings, even on
OSX or Linux. For example, here is a Windows project that
enforces CRLF line endings.
Martin Malek GIT Basics 2016 15 / 67
16. text eol=lf
Git will always convert line endings to LF on checkout. You
should use this for files that must keep LF endings, even on
Windows. For example, here is a project that enforces LF line
endings.
binary
Git will understand that the files specified are not text, and it
should not try to change them. The binary setting is also an alias
for -text -diff.
Martin Malek GIT Basics 2016 16 / 67
17. Storage
Figure 3: Instead of saving or replacing entire file, only differences are saved and
tracked.
Martin Malek GIT Basics 2016 17 / 67
18. Architecture
Index
▶ Stores information about current working directory and changes made
to it
Object Database
▶ Blobs (files)
⋆ Stored in .git/objects
⋆ Indexed by unique hash
⋆ All files are stored as blobs
▶ Trees (directories)
▶ Commits
⋆ One object for every commit
⋆ Contains hash of parent, name of author, time of commit, and hash of
the current tree
▶ Tags
Martin Malek GIT Basics 2016 18 / 67
22. Branching & Merging
Branching with Git is cheap and simpe
Considered one of the core parts of daily workflow
Martin Malek GIT Basics 2016 22 / 67
23. Main branches
Consider origin/production to be the main brach always ready for
deploy
Consider origin/master to be the main branch with the latest delivered
development changes for the next release
Consider origin/staging to be the main brach where the source code
always reflects a state for staging environment
Martin Malek GIT Basics 2016 23 / 67
24. Supporting branches
Unlike the main branches, these branches always have a limited life time
since they will be removed.
Each of these branches have a specific purpose and are bound to strict
rules as to which branches may be their originating branch and which
branches must be their merge target.
Used for:
Feature branches
Hotfix branches
Release branches
Martin Malek GIT Basics 2016 24 / 67
25. Release
Each time when changes are merged back into production, this is a
new production release by definition
Martin Malek GIT Basics 2016 25 / 67
26. Rebase vs Merge
Merging brings two lines of development together while preserving the
ancestry of each commit history.
In contract, rebasing unifies the lines of development by re-writing changes
from the source branch - effectively pretending that those commits were
written on top of the destination branch all along.
Rebase requires the commits on the source branch to be re-written, which
changes their content and their SHAS.
Martin Malek GIT Basics 2016 26 / 67
27. Merge
Pros
Simple to use and understand.
The commits on the source branch remain separate from other branch
commits, provided you don’t perform a fast-forward merge.
Existing commits on the source branch are unchanged and remain
valid; it doesn’t matter if they’ve been shared with others.
Cons
If the need to merge arises simply because multiple people are working
on the same branch in parallel, the merges don’t serve any useful
historic purpose and create clutter.
Martin Malek GIT Basics 2016 27 / 67
28. Merge
Fast-forward vs no Fast-forward
Fast-forward merging makes sense for short-lived branches, but in a
more complex history, non-fast-forward merging may make the history
easier to understand, and make it easier to revert a group of commits.
Avoid the ‘no-ff’ with its “checkpoint commits” that break bisect or
blame.
Martin Malek GIT Basics 2016 28 / 67
29. Rebase
Pros
Simplifies your history.
Is the most intuitive and clutter-free way to combine commits from
multipledevelopers in a shared branch.
Cons
Slightly more complex, especially under conflict conditions.
Rewriting of history has ramifications if you’ve previously pushed those
commits elsewhere.
Martin Malek GIT Basics 2016 29 / 67
31. Golden rule
Never ever rebase a branch that you pushed, or that you pulled from
another person
Martin Malek GIT Basics 2016 31 / 67
32. Merge or Rebase?
Push
Don’t do your work on the public branch, use feature branches.
When multiple developers work on a shared branch, push & rebase
your outgoing commits to keep history cleaner.
To re-integrate a completed feature branch, use merge (and opt-out of
fast-forward commits in Git).
Pull
To bring a feature branch up to date with its base branch, Prefer
rebasing your feature branch onto the latest base branch if You
haven’t pushed this branch anywhere yet, or you know for sure that
other people will not have checked out your feature branch.
Otherwise, merge the latest base changes into your feature branch.
Martin Malek GIT Basics 2016 32 / 67
33. Feature development
Pull to update your local master
Check out a feature branch from master
Do work in your feature branch, committing early and often
Rebase frequently to incorporate upstream changes
Interactive rebase (squash) your commits
Merge your changes with master
Push your changes to the upstream
Martin Malek GIT Basics 2016 33 / 67
34. Bug fixes
Same flow as feature development
Prefix the branch name with “bug” to help you keep track of them
Do work in your bugfix branch, committing early and often
Rebase frequently against the upstream
Use an interactive rebase to squash all the commits together
With a bugfix, squash the commits down into one and exactly one commit
that completely represents that bugfix. Half of a bugfix is useless!
Martin Malek GIT Basics 2016 34 / 67
36. What is cherry-pick
What git cherry-pick does, basically, is take a commit from somewhere else,
and “play it back” wherever you are right now.
git cherry-pick is for bringing an interesting commit from one line of
development to another.
A classic example is backporting a security fix made on an unstable
development branch to a stable (maintenance) branch.
Martin Malek GIT Basics 2016 36 / 67
38. What is tag?
In Git tag is a named reference to a specific commit in your repository. The
difference between tag and branch is that branches can change the commit
they point to while tags are immutable and always point to the same
commit. As a consequence it is impossible to add any new change to a tag.
Martin Malek GIT Basics 2016 38 / 67
39. Tag types
Git has three types of tags
lightweight
annotated
signed
git tag tag-name
Martin Malek GIT Basics 2016 39 / 67
40. Upstream
Tags are not pushed to upstream by default, to do that, run:
git push --tags
Martin Malek GIT Basics 2016 40 / 67
41. Difference
Lightweight tags are the most basic ones because they store only hash
of the commit they refer to.
Lightweight tags have several drawbacks which disqualify them in
many situations.
▶ They cannot have tag message, creation date, author or optionally
cryptographic signature.
▶ If you want this kind of information, you can create an unsigned
annotated tag by adding -a option.
It is also possible to create annotated tag signed using GnuPG
program by adding -s option
▶ The signed tag can be later verified whether is was created by an
authorized person.
Martin Malek GIT Basics 2016 41 / 67
43. Stash
Often, when you’ve been working on part of your project, things are in a
messy state and you want to switch branches for a bit to work on
something else. The problem is, you don’t want to do a commit of
half-done work just so you can get back to this point later. The answer to
this issue is the git stash command.
Stashing takes the dirty state of your working directory — that is, your
modified tracked files and staged changes — and saves it on a stack of
unfinished changes that you can reapply at any time.
Martin Malek GIT Basics 2016 43 / 67
44. Stashing your work
$ git stash
Saved working directory and index state
"WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
You can name your stash with git stash save name, by default identifier
of the stash will be stash@{0}.
Martin Malek GIT Basics 2016 44 / 67
45. Unstashing your work
git stash apply [name of the branch]
git stash pop [name of the branch]
Martin Malek GIT Basics 2016 45 / 67
46. Creating a repo from stash
If you stash some work, leave it there for a while, and continue on the
branch from which you stashed the work, you may have a problem
reapplying the work.
If you want an easier way to test the stashed changes again, you can run
git stash branch, which creates a new branch for you.
git stash branch testchanges
Martin Malek GIT Basics 2016 46 / 67
48. Fetch or clone (create a copy of the remote repository) (compare to
cvs check out)
Modify the files in the local branch
Stage the files (no cvs comparison)
Commit the files locally (no cvs comparison)
Push changes to remote repository (compare to cvs commit)
Martin Malek GIT Basics 2016 48 / 67
49. Multiple remote repositories
Instead of sticking to one central repository, git helps to deal with multiple
remote repository
Martin Malek GIT Basics 2016 49 / 67
55. Commiting
git commit -m "Message"
Realize you forgot to add the changes from main.py
git add main.py
git commit --amend --no-edit
Change author
git commit --amend --author="John Doe <john.doe@example.com>"
Martin Malek GIT Basics 2016 55 / 67
56. Author vs committer
The author is the person who originally wrote the code. The committer, on
the other hand, is assumed to be the person who committed the code on
behalf of the original author. This is important in Git because Git allows
you to rewrite history, or apply patches on behalf of another person.
Martin Malek GIT Basics 2016 56 / 67
57. Reverting
Git support git revert or to revert last commit i can run
git reset --soft HEAD^
To remove last commit:
git reset --hard HEAD^
Martin Malek GIT Basics 2016 57 / 67
59. Fetching from upstream
git fetch --all
git merge origin/master
Or
git pull
git fetch --all
git rebase origin/master
Or
git pull --rebase
Martin Malek GIT Basics 2016 59 / 67
60. Rebase
I’m working on feature branch, I want to update my code with changes
from master
git rebase origin/master
If there will be any conflict, I should resolve it (conflict per commit) and
run
git rebase --continue
If I want to abort the rebase (or merge)
git rebase --abort
Martin Malek GIT Basics 2016 60 / 67
61. Interactive rebase
To modify a commit that is farther back in your history, you must move to
more complex tools.
With the interactive rebase tool, you can then stop after each commit you
want to modify and change the message, add files, or do whatever you
wish.
Martin Malek GIT Basics 2016 61 / 67
62. Interactive rebase
For example, if you want to change the last three commit messages, or any
of the commit messages in that group.
git rebase -i HEAD~3
Running this command gives you a list of commits in your text editor that
looks something like this:
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
Martin Malek GIT Basics 2016 62 / 67
63. Interactive rebase
Reordering
You can also use interactive rebases to reorder or remove commits entirely.
If you want to remove the “added cat-file” commit and change the order in
which the other two commits are introduced you will just change order of
the lines.
Martin Malek GIT Basics 2016 63 / 67
64. Interactive rebase
Squashing Commits
It’s also possible to take a series of commits and squash them down into a
single commit with the interactive rebasing tool.
Martin Malek GIT Basics 2016 64 / 67
65. Interactive rebase
Splitting a Commit
Splitting a commit undoes a commit and then partially stages and commits
as many times as commits you want to end up with.
For example, suppose you want to split the middle commit of your three
commits. Instead of “updated README formatting and added blame”,
you want to split it into two commits: “updated README formatting” for
the first, and “added blame” for the second.
pick f7f3f6d changed my name a bit
edit 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
Martin Malek GIT Basics 2016 65 / 67