Viewing
the history
Of course, Git is able to
show the history of the repository. For that, the log command is
used:
git
log
If you try it, you will see
that the output is not very nice. The log command has many flags
available to draw pretty graphs. Here’s a suggestion for using this command
through this guide, even if graphs are shown for each scenario:
git log --all --graph --decorate --oneline
If you want, you can omit
the --oneline flag for showing the full information of each commit.
Independent development lines: branches
Branching is probably the
most powerful feature of Git. A branch represents an independent
development path. The branches coexist in the same repository, but each one has
its own history. In the previous section, we have worked with a branch, Git’s
default branch, which is named master.
Taking into account this, the proper way to express the history would be the following, considering the branches.
Creating a branch with Git is so
simple:
git branch <branch-name>
For example:
git branch second-branch
And that’s it. But, what is Git doing really when it creates a branch? It just creates a pointer with that branch name that points to the commit where the branch has been created:
This is one of the most
notable features of Git: the branch creation speed, almost instantaneous,
regardless of the repository size.
To start working in that
branch, we have to checkout it:
git checkout second-branch
Now, the commits will only exist in second-branch. Why? Because the HEAD now is pointing to second-branch, so, the history created from now will have an independent path from master.
We can see it making a couple of commits being located in second-branch:
echo 'The changes made in this branch...' >> README.txt
git
add README.txt
git
commit -m 'Start changes in second-branch'
echo
'... Only exist in this branch' >> README.txt
git
add README.txt
git
commit -m 'End changes in second-branch'
|
If we check for the content of the file we have being modifying, we will see the following:
Second
commit!
The
changes made in this branch...
...
Only exist in this branch
|
But, what if we return to master?
git
checkout master
|
The content of the file will be:
Second
commit!
|
This is because, after creating the history of second-branch, we have placed the HEAD pointing to master:
Combining
histories: merging branches
In the previous subsection,
we have seen how we can create different paths for our repository history. Now,
we are going to see how to combine them, what for Git is calling merging.
Let’s suppose that, after the changes made in second-branch, is ready to return to master. For that, we have to place the HEAD in the destination branch (master), and specify the branch that is going to be merged to this destination branch (second-branch), with merge command:
git checkout master
git
merge second-branch
|
And Git will give the following output:
Updating
f043d98..0705117
Fast-forward
README.txt
| 2 ++
1
file changed, 2 insertions(+)
|
Now, the history of the second-branch has been merged to master, so, all the changes made in this first branch have been applied to the second.
In this case, the entire
history of second-branch is now part of the history of master, having a graph
like the following:
As you can see, no track of
the life of second-branch has been saved, when you probably were
expecting a nice tree.
This is because Git merged the branch using the fast-forward mode. Note that is telling it in the merge output, shown above. Why did Git do this? Because master and second-branch shared the common ancestor, f043d98.
When we are merging branches, is always advisable not to use the fast-forward mode. This is achieved passing --no-ff flag while merging:
git merge --no-ff second-branch |
What does this really do? Well, it just creates an intermediate, third commit, between the HEAD, and the “from” branch’s last commit.
After saving the commit message (of course, is editable), the branch will be merged, having the following history:
Which is much more
expressive, since the history is reflected as it is actually is. The no
fast-forward mode should be always used.
A merge of a branch supposes the end of the life of this. So, it should be deleted:
git branch -d second-branch |
Of course, in the future, you can create again a second-branch named branch.
No comments:
Post a Comment