Knowing
in advance which version to stay with
It may happen that we know
beforehand which version we want to choose in case of conflicts. In these
cases, we can tell Git which version use, to make it apply it directly.
To do this, we have to pass
the -X option to merge, indicating which version use:
git merge -X
<ours|theirs> <branch-name>
|
So, for using HEAD version,
we would have to use ours option; instead, for using the version that
is not HEAD‘s, theirshas to be passed.
That is, the following:
git merge -X ours second-branch |
Would leave the file as is
shown:
1
2
3
|
one
two
three
|
And, the following:
git merge -X theirs
second-branch
|
As it follows:
1
2
3
|
one
two
three (from second-branch)
|
Checking differences
Git allows to check the
differences between distinct points in the history. This is done with diff option.
Interpreting
the differences
Before seeing what
differences we can look at, firstly we have to understand how the differences
are shown.
Let’s see a sample output of
a difference between the same file:
diff --git a/README.txt
b/README.txt
index 31325b6..55e8d58
100644
--- a/README.txt
+++ b/README.txt
@@ -1,2 +1,2 @@
-This is
-the original file
+This file
+has been modified
|
Here, a is the a
previous version of the file, and b the current version.
The third and fourth line
identifies each letter with a - or + symbol.
That @@ -1,2 +1,2 @@ is
called “hunk header”. This identifies the chunks of code that actually have
changed, not showing the common parts for both versions.
The format is the following:
@@
<previous><from-line>,<number-of-lines>
<current>,<from-line><number-of-lines>
|
In this case:
“previous”: identified
with -, corresponding to a.
“from-line”: the line number
from where the changes start.
“number-of-lines”: the
number of lines shown.
“current”: identified
with +, corresponding to b.
Finally, which lines are
subtracted, and which added, are shown. In this case, two lines have been
subtracted from the line (those preceded with -), and other two have been
added (preceded with +).
Differences
between working directory and last commit
One common use is to check
the differences between the working directory and the last commit. For this, is
enough to execute:
git diff |
Which will show the difference for every file. We can specify also specific files:
git diff <file1> <file2> |
Differences
between exact points in history
We can look for differences
with:
SHA1 id
Branch names
HEAD
Tags
Being combinable between
them.
The syntax is the following:
git diff <original>..<modified>
|
For example, the following
would show the changes that have been applied to dev branch, compared
to a v1.0 tag:
git diff v1.0..dev |
Tagging
important points:
Creating a tag is so simple, we just have to situate the HEAD in the point we want to tag, and just specify the tag name with the tag option:
For example:
Take into account that the tag names cannot be repeated in a repository.
<< Previous Next >>
Tagging is one of the nicest
features of Git, since allows to mark important points in the repository
history, in a very easy way. Usually, tags are used to mark releases, not only
for stable releases, but also for under-development or incomplete releases,
such as:
Alpha
Beta
Release candidate (rc)
Creating a tag is so simple, we just have to situate the HEAD in the point we want to tag, and just specify the tag name with the tag option:
git tag -a <tag-name> |
For example:
git tag -a v0.1-beta1
|
Then, we will be asked to
type a message for the tag. Typically, the changes made from last tag are
specified.
As when committing, we can
specify the tag message inline, with -m flag:
git tag -a v0.1 -m 'v0.1 stable release, changes from...' |
Take into account that the tag names cannot be repeated in a repository.
Undoing
and deleting things
Git also allows to undo and
modify some things in the history. In this section we will see what can be
done, and how.
Modifying the last commit
Is quite common to want to
modify the last commit, for example, when just a line of code has to be added;
or even to modify the update message, without changing any file.
For that, Git has the --amend flag
for commit command:
git commit --amend
|
This is just the same as
committing, but, instead of a new commit object, the last one of that branch
will be overwritten.
Discarding
uncommitted changes
This is for, after a commit,
when we keep developing, we think that we have taken an incorrect path, and we
want to reset the changes, returning to the last commit’s state.
For this, the command used
is checkout, as for moving between branches. But, when specifying a file,
this gets reseted to the state of the last commit.
For example:
echo 'one' > test.txt
git add test.txt
git commit -m 'commit one'
echo 'two' > test.txt
git checkout test.txt #
The content of test.txt is now 'one'.
|
Deleting
commits
Usually, we want to delete
commits when we don’t want to leave any record of an embarrassing commit, or
just for removing useless changes.
This is achieved moving the
branch or HEAD pointers. Moving the pointers to previous commits makes
the commits remaining ahead get “lost”, unlinked from the linked list. To move
them, reset command is used.
There are two ways of making
a reset: not touching the working directory (soft reset, --soft flag),
or resetting it too (hard reset, --hard flag). That is, if you
make a soft reset, the commit(s) will be removed, but the modifications saved
in that/those commit(s) will remain; and a hard reset, won’t leave change made
in the commit(s). If no flag is specified, the reset will be done softly.
Let’s start resetting
things. The following command would remove the last commit, i.e., the commit
where HEAD is pointing to:
git reset --hard HEAD~ |
The ~ character is
for indicating an ancestor. Used once, indicates the immediate parent; twice,
the grandparent; and so on. But, instead of typing ~ n times, we
can specify the n ancestors that we want to remove:
git reset --hard HEAD~3 |
Which would remove the last
3 commits.
You may have noticed that
this may cause conflicts with those commits with more than one ancestor, i.e.,
the result of a not fast-forwarded merge. Well, it doesn’t cause any problem:
the followed parent using HEAD~ is always the first one. But there’s
a way to decide which of the common parents follow: ^, followed by the
parent number. So, the following:
git reset --hard HEAD~2^2 |
Would remove the previous
two commits, but taking the path of the second ancestor.
Even if it is possible to
specify which ancestor path follow, is recommended to always use the
syntax for first ancestor (only ~) since it’s easier, even if
more commands would be required (since you would have to checkout the
different branches to update HEAD position).
Deleting tags
Deleting tags is so simple:
git tag -d <tag-name> |
<< Previous Next >>
No comments:
Post a Comment