GIT Part-8


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.

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