Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
uva
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
uva
Commits
86e0cab7
Commit
86e0cab7
authored
Jan 09, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Portfolio: added version control system.
parent
797c9cc8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
563 additions
and
0 deletions
+563
-0
portfolio/vcs/Makefile
portfolio/vcs/Makefile
+4
-0
portfolio/vcs/benchmarks.png
portfolio/vcs/benchmarks.png
+0
-0
portfolio/vcs/vcs.tex
portfolio/vcs/vcs.tex
+559
-0
No files found.
portfolio/vcs/Makefile
0 → 100644
View file @
86e0cab7
all
:
vcs.pdf
%.pdf
:
%.tex
pdflatex
$^
portfolio/vcs/benchmarks.png
0 → 100644
View file @
86e0cab7
10.3 KB
portfolio/vcs/vcs.tex
0 → 100644
View file @
86e0cab7
\documentclass
[10pt,a4paper]
{
article
}
\usepackage
{
float
}
\usepackage
{
graphicx
}
\usepackage
{
hyperref
}
\usepackage
{
enumerate
}
\title
{
Portfolio - Version control system
}
\author
{
Sander van Veen, Computer Science, University of Amsterdam
}
\begin{document}
\maketitle
\tableofcontents
\pagebreak
\section
{
Why did I choose git?
}
% {{{
\label
{
sec:why-did-i-choose-git
}
There are a couple of reasons why you should choose Git, or one of the other
decentralized version control systems:
\begin{enumerate}
\item
Git is free libre open source software, which allows me to use the
software to its full potential, thus without any limitations.
\item
Generally speaking, decentralized version control systems are faster
than centralized due to the network latency. A decentralized system has all
the commit history and branches on the local hard disk.
\item
Decentralized means no single point of failure. Every user has what
is essentially a full backup of the main server, each of which could be
pushed up to replace the main server in the event of a crash or corruption.
There is basically no single point of failure with Git unless there is only
a single point.
\item
Git is fast compared to all version control systems (even compared to
the decentralized ones).
\footnote
{
Benchmark used for comparison:
\url
{
http://whygitisbetterthanx.com/
}}
Git is designed to be fast,
especially in merging branches. It is developed to support the kernel
development and Linus Torvalds was one of Git's core developers.
\begin{figure}
[H]
\label
{
fig:benchmarks
}
\centering
\includegraphics
[width=\textwidth]
{
benchmarks.png
}
\caption
{
Benchmark of the most popular decentralized version control
systems. Lower bars (less time to accomplish a task) are better: git is a
clear winner.
}
\end{figure}
\end{enumerate}
Therefore, I see no reason to use a centralized version control system.
Decentralized allows you to do everything as you would do with centralized
system, but faster. If you have some legacy code depending on a Subversion
repository, you could use
\texttt
{
git-svn
}
. This script makes it possible to
have all benefits of Git and use the old Subversion repository. In the mean
time, you can migrate the Subversion repository (and all its dependencies) to a
Git repository.
% }}}
\section
{
Assignment
}
% {{{
\label
{
sec:Assignment
}
First, I'll create an empty Git repository. The option
\texttt
{
--bare
}
is used
to create a bare repository: no working tree, just the content of the
\texttt
{
.git
}
directory. A bare repository is a so-called ``public'' repository,
allowing others to push their changes to. Non-bare repositories are considered
``private''. You will see an error if you push to a private repository,
because the push can/will mess up the working tree of the repository.
\begin{verbatim}
$
git init
--
bare
/
tmp
/
test.git
Initialized empty Git repository in
/
tmp
/
test.git
/
\end
{
verbatim
}
\subsection
{
Clone repository and add some content
}
% {{{
\label
{
sub:clone
-
repository
-
and
-
add
-
some
-
content
}
\begin
{
verbatim
}
$
cd /tmp/uva-git/
$
git clone
/
tmp
/
test.git a
Initialized empty Git repository in
/
tmp
/
uva
-
git
/
a
/
.git
/
warning: You appear to have cloned an empty repository.
\end
{
verbatim
}
\noindent
Currently, the repository is empty
(
notice the warning
)
.
Therefore, I will add some example data to the repository.
\begin
{
verbatim
}
$
echo "foo bar" > baz.txt
$
git add baz.txt
$
git commit -am "Added 'foo bar'."
[master (root-commit) a811fdc] Added 'foo bar'.
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 baz.txt
\end{verbatim}
\noindent
And a second commit.
\begin{verbatim}
$
echo "
42
" >> baz.txt
$
git commit -am "Added '42'."
[master 235d628] Added '42'.
1 files changed, 1 insertions(+), 0 deletions(-)
\end{verbatim}
% }}}
\subsection
{
File difference
}
% {{{
\label
{
sub:File difference
}
View the file difference between two versions of the file
\texttt
{
baz.txt
}
.
\begin{verbatim}
git diff a811fdcc6b926a462ac2217f26f81a760fbad99d baz.txt
diff --git a/baz.txt b/baz.txt
index d675fa4..20de225 100644
--- a/baz.txt
+++ b/baz.txt
@@ -1 +1,2 @@
foo bar
+42
\end{verbatim}
\noindent
The second part of the question is ambiguous. Therefore, I'll answer
both interpretations:
\begin{enumerate}
\item
Using
\texttt
{
diff
}
, a user can compare two files. Thus, if you
checkout two versions of a file on disk, you can compare those files using
\texttt
{
diff a/foo.txt b/foo.txt
}
.
\item
Perhaps is the question referring to a centralized repository. In that
case, it is not possible to compare two versions of the file. Since Git
stores everything locally, comparing is possible without an internet
connection (which is required for most centralized repositories).
\end{enumerate}
% }}}
\subsection
{
Show commit history
}
% {{{
\label
{
sub:show-commit-history
}
If you want an overview of the commit history, you would usually use
\texttt
{
git
shortlog
}
, since it will print the commit titles only (that's one of the reasons
why proper commit messages are required).
\begin{verbatim}
$
git shortlog
Sander van Veen
(
2
)
:
Added 'foo bar'.
Added '
42
'.
\end
{
verbatim
}
\noindent
The title of a commit message is at most
50
characters. This
50
char
limit is not a hard limit, but a good thing to do. The rest of the message is
stored in the ``body'' of a commit. The title should summarize the commit body
(
just like an e
-
mail
)
. Use
\texttt
{
git log
}
to show the more detailed history.
\begin
{
verbatim
}
$
git log
commit 235d62817d1ca1977e4e16e440d80ee615b9b8f2
Author: Sander van Veen <sandervv@gmail.com>
Date: Sun Jan 9 16:49:12 2011 +0100
Added '42'.
commit a811fdcc6b926a462ac2217f26f81a760fbad99d
Author: Sander van Veen <sandervv@gmail.com>
Date: Sun Jan 9 16:46:00 2011 +0100
Added 'foo bar'.
\end{verbatim}
% }}}
\subsection
{
Clone second repository
}
% {{{
\label
{
sub:Clone second repository
}
Since I have changed the repository, I'll push the committed content to the
public repository using
\texttt
{
git push
}
. This command requires a location and
which branch/branches you want to push. In this example, the location is
\texttt
{
/tmp/test.git
}
,
\texttt
{
master
}
is the name of the local branch and the
second
\texttt
{
master
}
is the name of the remote branch (branch names separated
by a double colon).
\begin{verbatim}
$
git push
/
tmp
/
test.git master:master
Counting objects:
6
, done.
Delta compression using up to
2
threads.
Compressing objects:
100
% (2/2), done.
Writing objects:
100
% (6/6), 447 bytes, done.
Total
6
(
delta
0
)
, reused
0
(
delta
0
)
Unpacking objects:
100
% (6/6), done.
To
/
tmp
/
test.git
*
[
new branch
]
master
-
> master
\end
{
verbatim
}
\noindent
Notice the creation of the remote branch
\texttt
{
master
}
.
It was not necessary to push the content before cloning the repository, but it
will reduce the work to create a copy of the repository, if you push the changes
before cloning. Otherwise, your second repository will be empty. After pushing
the commits, clone the public repository.
\begin
{
verbatim
}
git clone
/
tmp
/
test.git
/
tmp
/
uva
-
git
/
b
\end
{
verbatim
}
% }}}
\subsection
{
Conflicts and conflict solving
}
% {{{
\label
{
sub:conflicts
-
and
-
conflict
-
solving
}
Creating a conflict is easy. First, add some content to a new file in the first
repository. Then, add some content to a file with the same name as in the first
repository in the second repository.
\begin
{
verbatim
}
$
cd /tmp/uva-git/a
$
echo "abc" > conflict.txt
$
git add conflict.txt
$
git commit
-
m "Added 'abc' to demonstrate a conflict."
[
master
6271
a
34
]
Added 'abc' to demonstrate a conflict.
1
files changed,
1
insertions
(+)
,
0
deletions
(-)
create mode
100644
conflict.txt
$
git push /tmp/test.git master:master
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100
% (2/2), done.
Writing objects: 100
% (3/3), 300 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100
% (3/3), done.
To /tmp/test.git
235d628..6271a34 master -> master
\end{verbatim}
\noindent
Everything is good so far, now create the same file in the second
repository. Notice that until the line containing
\texttt
{
git push
}
, there are
no errors. Once
\texttt
{
git push
}
is invoked, errors occur
\texttt
{
[rejected]
}
, because Git is unable to push the changes.
\begin{verbatim}
$
cd
/
tmp
/
uva
-
git
/
b
$
echo "def" > conflict.txt
$
git add conflict.txt
$
git commit -m "Added 'def' to demonstrate a conflict."
[master ebd14e1] Added 'def' to demonstrate a conflict.
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 conflict.txt
$
git push
/
tmp
/
test.git master:master
To
/
tmp
/
test.git
!
[
rejected
]
master
-
> master
(
non
-
fast
-
forward
)
error: failed to push some refs to '
/
tmp
/
test.git'
To prevent you from losing history, non
-
fast
-
forward updates were rejected
Merge the remote changes before pushing again. See the 'Note about
fast
-
forwards' section of 'git push
--
help' for details.
# Thus, pull the changes, merge them and then push.
$
git pull
remote: Counting objects: 4, done.
remote: Compressing objects: 100
% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100
% (3/3), done.
From /tmp/test
235d628..6271a34 master -> origin/master
Auto-merging conflict.txt
CONFLICT (add/add): Merge conflict in conflict.txt
Automatic merge failed; fix conflicts and then commit the result.
\end{verbatim}
\noindent
Git is unable to solve this conflict, because it does not know which
content is good and which is garbage. This conflict can be solved by editing
the conflicted file manually:
\begin{verbatim}
$
cat conflict.txt
<<<<<<< HEAD
def
=======
abc
>>>>>>>
6271
a
34
de
1458
b
0
b
8
e
7
edfc
683
b
476
aef
84
bf
631
$
vim conflict.txt
$
cat conflict.txt
def
\end
{
verbatim
}
\noindent
Once the merging is done, you can commit the merged content and push.
\begin
{
verbatim
}
$
git add conflict.txt
$
git commit
-
m "Solved conflict."
[
master
9
f
66
c
7
b
]
Solved conflict.
$
git push
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100
% (3/3), done.
Writing objects: 100
% (4/4), 485 bytes, done.
Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100
% (4/4), done.
To /tmp/test.git
6271a34..9f66c7b master -> master
\end{verbatim}
% }}}
\subsection
{
Pull before push
}
% {{{
\label
{
sub:pull-before-push
}
As mentioned in chapter
\ref
{
sub:conflicts-and-conflict-solving
}
, it is
necessary to pull before pushing content. Your version of the content should be
up-to-date and in case of a conflict, you should merge conflicts locally.
% }}}
\subsection
{
Simulate conflicts
}
% {{{
\label
{
sub:simulate-conflicts
}
See chapter
\ref
{
sub:conflicts-and-conflict-solving
}
for conflicts and solving
conflicts.
% }}}
\subsection
{
Adding files and directories
}
% {{{
\label
{
sub:adding-files-and-directories
}
Adding files to Git is done using the
\texttt
{
git add
}
command. But there is a
difference between Git and other version control systems: Git tracks content not
files. Git takes a snapshot of the file, when you add the file using
\texttt
{
git
add
}
. Other version control systems start to track changes when the file is
added. Git requires adding new and modified files and in
both cases it takes a snapshot of the given files and stages that content in the
index, ready for inclusion in the next commit.
According to the Git FAQ
\footnote
{
\url
{
https://git.wiki.kernel.org/index.php/GitFaq
\#
Can
_
I
_
add
_
empty
_
directories.3F
}}
,
it is not possible to add an empty directory to the git repository:
\begin{quote}
Currently the design of the git index (staging area) only permits files to be
listed, and nobody competent enough to make the change to allow empty
directories has cared enough about this situation to remedy it.
Directories are added automatically when adding files inside them. That is,
directories never have to be added to the repository, and are not tracked on
their own.
You can use "
\texttt
{
git add <dir>
}
" and it will add files in there.
If you really need a directory to exist in checkouts you should create a file in
it.
\texttt
{
.gitignore
}
works well for this purpose; you can leave it empty, or
fill in the names of files you expect to show up in the directory.
\end{quote}
% }}}
\subsection
{
Renaming files
}
% {{{
\label
{
sub:renaming-files
}
In Git, it is not necessary to mention the renaming of files (since Git tracks
content, not files). However, it is required to add the renamed file to Git's
index, otherwise the file is marked as ``deleted''. Git provides a command to
move (or rename) files and directories:
\texttt
{
git mv foo bar
}
.
% }}}
\subsection
{
Discarding changes
}
% {{{
\label
{
sub:discarding-changes
}
If you suddenly think your changes are not necessary or not the right solution,
you can discard those changes in Git using
\texttt
{
git checkout -- baz.txt
}
. Or you
could reset your source tree to the last commit (thus discarding all changes in
all tracked files made since the last commit) using
\texttt
{
git reset --hard HEAD
}
.
% }}}
\subsection
{
Going back to a previous commit
}
% {{{
\label
{
sub:going-back-to-a-previous-commit
}
Use
\texttt
{
git checkout REV
}
to go a (previous) commit state.
\begin{verbatim}
$
ls
-
1
baz.txt
conflict.txt
$
git checkout 235d62817d1ca1977e4e16e440d80ee615b9b8f2
Note: checking out '235d62817d1ca1977e4e16e440d80ee615b9b8f2'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new
_
branch
_
name
HEAD is now at 235d628... Added '42'.
$
ls
-
1
baz.txt
\end
{
verbatim
}
% }}}
\subsection
{
Delete a file and revert
}
% {{{
\label
{
sub:Delete a file and revert
}
When deleting a file outside the repository, you could use
\texttt
{
git checkout
FILE
}
to restore the file.
\begin
{
verbatim
}
$
ls -1
baz.txt
conflict.txt
$
rm conflict.txt
$
git status
# Not currently on any branch.
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: conflict.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$
ls
-
1
baz.txt
$
git checkout conflict.txt
$
ls
-
1
baz.txt
conflict.txt
\end
{
verbatim
}
When a file is deleted and committed to the repository, you could revert this
commit using
\texttt
{
git revert REV
}
. This will revert the commit and will
commit the result of the reversion to the repository. If you don't want to
commit the result after the reversion, provide the
\texttt
{
-
n
}
flag while using
\texttt
{
git revert
}
. This is useful when reverting more than one commits' effect
to your index in a row.
% }}}
\subsection
{
Branches
}
% {{{
\label
{
sub:Branches
}
When you want to create an experimental feature, which will break functionality,
it is wise to create a branch. Creating a branch makes it possible to commit
your changes, while other developers can continue their work. If you do not
create a branch, it is possible that the other developers cannot continue,
because your commit broke some functionality they are depending on. When your
feature is stable, you can merge the two branches and your feature is included
in the ``main'' source tree. Branches enable parallel development across the
developers. Git is designed to handle large branches and merging those branches
efficiently. Also notice when pulling from a Git repository, Git will
automatically merge two branches
(
your repository and the public repository
)
.
Consider the situation where we need to create a branch. The following commands
will create a branch of the master branch, commit some changes in both branches
and then merging the two branches. In this after the merge, only master branch
is available.
\begin
{
verbatim
}
$
git branch
* master
$
git branch foo
$
git checkout foo
Switched to branch 'foo'
$
git branch
*
foo
master
$
ls
baz.txt conflict.txt
$
cat baz.txt
foo bar
42
$
echo "foo bar" > baz.txt
$
echo "baz" >> baz.txt
$
git commit -am "Addded 'baz' and removed '42'."
[foo dbf6e7d] Addded 'baz' and removed '42'.
1 files changed, 1 insertions(+), 1 deletions(-)
$
echo "ABC" > abc.txt
$
git add abc.txt
$
git commit
-
am "Added ABC."
[
foo
2
ef
3
c
7
e
]
Added ABC.
1
files changed,
1
insertions
(+)
,
0
deletions
(-)
create mode
100644
abc.txt
$
git checkout master
Switched to branch 'master'
$
cat baz.txt
foo bar
42
$
vim baz.txt
$
git commit
-
am "Added 'ghi'."
[
master
16
f
0
f
26
]
Added 'ghi'.
1
files changed,
1
insertions
(+)
,
0
deletions
(-)
$
git checkout foo
Switched to branch 'foo'
$
cat baz.txt
foo bar
baz
$
git merge master
Auto-merging baz.txt
CONFLICT (content): Merge conflict in baz.txt
Automatic merge failed; fix conflicts and then commit the result.
$
git branch
*
foo
master
$
vim baz.txt
$
cat baz.txt
foo bar
baz
42
$
git commit -am "Fixed merge conflict."
[foo 31469f3] Fixed merge conflict.
$
git branch
*
foo
master
$
git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
$
git merge foo
Updating
16
f
0
f
26
..
31469
f
3
Fast
-
forward
abc.txt |
1
+
baz.txt |
2
+-
2
files changed,
2
insertions
(+)
,
1
deletions
(-)
create mode
100644
abc.txt
$
cat baz.txt
foo bar
baz
42
\end{verbatim}
In the example above,
\texttt
{
git branch
}
is used to list the available
branches. The asterisk before a branch name indicates the currently used branch.
It is not necessary to use
\texttt
{
git branch
}
, but it is used in this example to
show which branch is active.
You could delete a branch with
{
git branch -d BRANCH
}
\begin{verbatim}
$
git branch
-
d foo
Deleted branch foo
(
was
31469
f
3
)
.
\end
{
verbatim
}
% }}}
\subsection
{
Cherry picking
}
% {{{
\label
{
sub:cherry
-
picking
}
Cherry picking
% }}}
% }}}
\end
{
document
}
% vim: foldmethod=marker:
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment