Patches
You will have probably ever
seen a software being updated with something called patch. A patch is just
a file that describes the changes that have to be made over a program,
indicating which code lines have to be removed, and which have to be added.
With Git, a path is just the output of a diff saved into a file.
Take into account that a
patch is an update, but an update does not have to be a patch
necessarily. Patches are thought for hotfixes, or also critical features
that have to be fixed or implemented right now, not for being the common
update and deploying strategy.
Creating
patches
As said, a patch for Git is
just the output of a diff. So, we would have to redirect that output to a
file:
git diff <expression>
> <patch-name>.patch # The extension is not important.
|
For example:
git diff master..issue-1
> issue-1-fix.patch
|
Note: a patch cannot be modified. If a patch file suffers any modification, Git will mark it as corrupt and it won’t apply it.
Applying patches
The patches are applied
with apply command. It’s as simple as specifying the path to the path
file:
git apply <patch-file> |
If patching goes well, no message will be displayed (if you haven’t used the --verbose flag). If the patch is not applicable, Git will show which are the files causing problems.
Is quite common to get
errors due to just whitespace differences. These errors can be ignored
with --ignore-space-changeand --ignore-whitespace flags.
Cherry picking
There may be some scenarios
in where we are interested in porting into a branch just a specific set of
changes made on another branch, instead of merging it.
To do this, Git allows to cherry pick commits from branches, with the cherry-pick command. The mechanism is the same as merging, but, in this case, specifying the commit SHA1 id, for example:
git cherry-pick -x aba6c1b # Several commits can be cherry picked. |
A cherry pick creates a new commit, with the same message as the original’s one. The -x option is for adding to that commit message a line indicating that is a cherry pick, and from which commit has been picked:
(cherry picked from commit
aba6c1bf9a0a7d6d9ccceeab2b5dfc64f6c115c2)
The cherry picking should
not be a recurrent practice in your workflow, since it does not leave a track
in the history, just a line indicating where has been picked from.
Hooks
Git hooks are custom
scripts that are triggered when important events occur, for example, a commit
or a merge.
Let’s say that you want to notify
someone with an email when your production branch is updated, or to run a test
suite; but in an automated way. The hooks can do this for you.
The scripts are located
in .git/hooks directory. By default, some sample hooks are provided.
Each hook has to have a concrete name, that we will see later, with no extension; and has to be marked as executable. You can use other scripting languages such us PHP or Python, apart from shell code.
Each hook has to have a concrete name, that we will see later, with no extension; and has to be marked as executable. You can use other scripting languages such us PHP or Python, apart from shell code.
There are two kind of hooks:
client-side, and server-side.
Client-side
hooks
The client-side hooks are
those that are fired when the local repository suffers changes. These are the
most common:
pre-commit: invoked by git commit command, before the commit is saved. A commit can be aborted with this hook exiting with a non-zero status.
post-commit: invoked by git commit too, but this time when the commit has been saved. At this point, the commit cannot be aborted.
post-merge: as same as with post-commit, but being this one fired by git merge.
pre-push: fired by git push, before the remote any object has been transferred.
The following script shows
an example applicable for both post-commit and post-commit hooks,
for notification purposes:
#!/bin/sh
branch=$(git rev-parse
--abbrev-ref HEAD)
if [ "$branch" =
"master" ]; then
echo
"Notifying release to everyone..."
#
Send the notification...
fi
|
To use it for both cases,
you would have to create both hooks.
Server-side
hooks
These hooks reside in the
server where the remote repository is hosted. As it is obvious, if you are
using services such as GitHub for hosting your repositories, you won’t be
permitted to execute arbitrary code. In GitHub’s case, you have available
third-party services, but never hooks with your own code. For using executing
your code, you will have to have your own server for hosting.
The most used hooks are:
pre-receive: this is fired
after someone makes a push, and before the references get updated in the
remote. So, with this hook, you can deny any push.
update: almost exact to the previous one, but this is executed for each reference pushed. That is, if 5 references have been pushed, this hook will be executed 5 times, unlike pre-receive, which is executed for the push as a whole.
post-receive: this one is executed once the push has been successful, so it can be used for notification purposes also.
Hooks
are not included in the history
The hooks only exist in the
local repository. If you make a push in a repository that has custom hooks,
these will not be sent to the remote. So, if every developer should share the
same hooks, they would have to be included in the working directory, and
installed them manually.
An
approach to Continuous Integration
Continuous Integration (CI)
is a software engineering practice that is closely related to version
controlling, and it’s worth mentioning it, at least to know it conceptually.
CI consists on making
several integrations of the code (at least, once a day), in a completely
automated way, with the aim of finding errors in early phases of the
development.
The concept is almost the
same of the hooks, but in a much more scalable and maintainable way.
Here are some of the actions
that are performed in each integration:
Test execution: unit,
acceptance, integration, regression, and a large etc.
Quality Assurance, with
software metrics checking: cyclomatic complexity, code coverage, and another
large etc.
Software coding standard compliance checking:
Continuous Integration
allows to perform those actions, and more, automatically, without the need of
having to execute it manually, just with a push or commit. Interesting,
isn’t it?
Probably, the most used CI
options are the following:
Travis CI: cloud-based,
which allows to fire integrations with pushes, without the need of having your
own server.
Jenkins: self-hosted, for
which a server is needed, but which is completely configurable. Compatible with
many build tools, like Ant, Gradle, Maven, Phing, Grunt…
No comments:
Post a Comment