diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ff85e8359a2edef24b667b0451522a3e0027188e..8079cb544b52c5e28866425f276319c46bb71c31 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,8 +10,11 @@ cache:
 
 lint:
   script:
-    - pip install pep8
+    # Pylint 1.6.4 does not fully support PEP 484 type hints, which is why we also use pep8.
+    # When pylint 2.0 is released we could rely solely on pylint (without the --disable option) and remove pep8.
+    - pip install pep8 pylint
     - pep8 --max-line-length=120 vcsinfo/ tests/
+    - pylint --max-line-length=120 --reports=no --disable=R,C vcsinfo
 
 test:
   script:
diff --git a/README.md b/README.md
index 445d703ff443d2a6b998572d7c8349562a7e524d..8d45026ad92e9894b85b0c8e9d304b1933d4bf39 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Python abstraction layer for getting info from VCSes sych as git.
 ## Installation
 
 ```
-$ pip install git+https://gitlab.astro-wise.org/omegacen/vcsinfo.git
+$ pip install git+https://gitlab.astro-wise.org/omegacen/vcsinfo.git@master
 ```
 
 ## Usage
@@ -19,9 +19,9 @@ You will first need instantiate a `Repository` instance. The preferred way
 to do this is via the factory method:
 
 ```python
-from vcsinfo.factory import build
+import vcsinfo.factory
 
-repo = build('/path/to/my/git/repo')
+repo = vcsinfo.factory.build('/path/to/my/git/repo')
 ```
 
 The `repo` object can then be queried for info:
diff --git a/tests/test_git.py b/tests/test_git.py
index 2c963a458bd5a244e91d9878212eeb68d68952d7..25761a114125050d4d083ae3b2240841e0984bb1 100644
--- a/tests/test_git.py
+++ b/tests/test_git.py
@@ -1,7 +1,9 @@
-import pytest
-import subprocess
-import os
 import datetime
+import os
+import subprocess
+
+import pytest
+
 from vcsinfo.vcsinfo import Repository
 from vcsinfo.factory import build
 from vcsinfo.exceptions import InvalidInputError, VcsError
diff --git a/vcsinfo/implementations/git.py b/vcsinfo/implementations/git.py
index 98745adb4e4024f2c4f74342095c403d8e05819a..06272ddaee2cfbb3625cba3bf69c5338eea8760c 100644
--- a/vcsinfo/implementations/git.py
+++ b/vcsinfo/implementations/git.py
@@ -1,16 +1,18 @@
 """Git implementation of the VCS Info interfaces."""
 
-from ..vcsinfo import Repository, Version
-from ..exceptions import InvalidInputError, VcsError
-from datetime import datetime
-from os.path import abspath
-from pkg_resources import parse_version
-from typing import Optional, Iterable
+import datetime
 import fnmatch
 import functools
+import os.path
 import re
+import typing
 import subprocess
 
+import pkg_resources
+
+from ..vcsinfo import Repository, Version
+from ..exceptions import InvalidInputError, VcsError
+
 
 class GitRepository(Repository):
     """Git implementation of a VCS repository."""
@@ -27,7 +29,7 @@ class GitRepository(Repository):
             raise InvalidInputError('{path} is not a git repository'.format(path=path))
 
         super().__init__(path)
-        self.__path = abspath(path)
+        self.__path = os.path.abspath(path)
 
     @property
     def path(self) -> str:
@@ -45,13 +47,13 @@ class GitRepository(Repository):
         """Check whether git is installed."""
         try:
             output = subprocess.check_output(['git', '--version']).decode().strip()
-            git_version = re.search('([0-9]+\.)+[0-9]+', output).group(0)
-            return parse_version(cls.required_git_version) <= parse_version(git_version)
+            git_version = re.search(r'([0-9]+\.)+[0-9]+', output).group(0)
+            return pkg_resources.parse_version(cls.required_git_version) <= pkg_resources.parse_version(git_version)
         except (IndexError, FileNotFoundError, subprocess.CalledProcessError):
             return False
 
     @property
-    def branches(self) -> Iterable[str]:
+    def branches(self) -> typing.Iterable[str]:
         """Return all references (branches, tags) of this repository."""
         self.fetch()
         return self.__run_git_command([
@@ -61,11 +63,12 @@ class GitRepository(Repository):
         ]).split('\n')
 
     @property
-    def remotes(self) -> Iterable[str]:
+    def remotes(self) -> typing.Iterable[str]:
         """Return all remotes of this repository."""
         return self.__run_git_command(['remote']).split('\n')
 
     def fetch(self) -> None:
+        """Fetch updates from remote repositories."""
         self.__run_git_command(['fetch', '--all'])
 
     def __run_git_command(self, params: list) -> str:
@@ -96,9 +99,9 @@ class GitVersion(Version):
             raise InvalidInputError('{rev} is not a valid git revision'.format(rev=rev))
 
     @property
-    def date(self) -> datetime:
+    def date(self) -> datetime.datetime:
         timestamp = self.__run_git_command(['show', '-s', '--format=%ct', self.id])
-        return datetime.fromtimestamp(int(timestamp))
+        return datetime.datetime.fromtimestamp(int(timestamp))
 
     @property
     def repository(self) -> GitRepository:
@@ -145,25 +148,25 @@ class GitVersion(Version):
             version += '.{symbol}'.format(symbol=replaced)
         return version
 
-    def newest(self, branch: Optional[str] = None) -> 'GitVersion':
+    def newest(self, branch: str = None) -> 'GitVersion':
 
         self.repository.fetch()
 
         if branch is not None:
-            pattern = '(({remotes})\/)?{branch}'.format(
+            pattern = r'(({remotes})\/)?{branch}'.format(
                 remotes='|'.join(self.repository.remotes),
                 branch=fnmatch.translate(branch)
             )
             regex = re.compile(pattern)
 
         versions = []
-        for b in self.repository.branches:
-            if branch is not None and not regex.match(b):
+        for rep_branch in self.repository.branches:
+            if branch is not None and not regex.match(rep_branch):
                 continue
-            v = GitVersion(self.repository, b)
-            if not self.is_ancestor_of(v):
+            version = GitVersion(self.repository, rep_branch)
+            if not self.is_ancestor_of(version):
                 continue
-            versions.append(v)
+            versions.append(version)
 
         if versions:
             return max(versions)
@@ -180,7 +183,7 @@ class GitVersion(Version):
         except subprocess.CalledProcessError:
             return False
 
-    def last_change_on(self, filename: str) -> Optional['GitVersion']:
+    def last_change_on(self, filename: str) -> typing.Optional['GitVersion']:
         """Return the last version which changed the given file, looking back from this version.
 
         Returns:
diff --git a/vcsinfo/vcsinfo.py b/vcsinfo/vcsinfo.py
index 6eccfd83ebeba41205a9c4640c014733b245bf9a..a0e045c24c0a311b7d5936e1ea1bec9758862a98 100644
--- a/vcsinfo/vcsinfo.py
+++ b/vcsinfo/vcsinfo.py
@@ -1,14 +1,14 @@
 """Interfaces for VCS repositories and versions"""
 
-from abc import ABC, abstractmethod
-from datetime import datetime
-from typing import Optional
+import abc
+import datetime
+import typing
 
 
-class Repository(ABC):
+class Repository(abc.ABC):
     """Interface for VCS repositories."""
 
-    @abstractmethod
+    @abc.abstractmethod
     def __init__(self, path: str) -> None:
         """Repository constructor.
 
@@ -18,18 +18,18 @@ class Repository(ABC):
         pass
 
     @property
-    @abstractmethod
+    @abc.abstractmethod
     def path(self) -> str:
         """Return the path of this repository."""
         pass
 
     @classmethod
-    @abstractmethod
+    @abc.abstractmethod
     def is_compatible_path(cls, path: str) -> bool:
         """Check whether the given path is compatible with this type of VCS repository."""
         pass
 
-    @abstractmethod
+    @abc.abstractmethod
     def current_version(self) -> 'Version':
         """Return the current version of the repository."""
         pass
@@ -39,37 +39,37 @@ class Repository(ABC):
         return self.path == other.path
 
 
-class Version(ABC):
+class Version(abc.ABC):
     """Interface for versions of a VCS repository
 
     A version always describes the repository as a whole, not just a single file.
     """
 
     @property
-    @abstractmethod
+    @abc.abstractmethod
     def id(self) -> str:
         """The unique identifier of this version."""
         pass
 
     @property
-    @abstractmethod
+    @abc.abstractmethod
     def version_id(self) -> str:
         """PEP 440 compatible version identifier."""
 
     @property
-    @abstractmethod
-    def date(self) -> datetime:
+    @abc.abstractmethod
+    def date(self) -> datetime.datetime:
         """The date this version was created."""
         pass
 
     @property
-    @abstractmethod
+    @abc.abstractmethod
     def repository(self) -> Repository:
         """The parent repository of this version."""
         pass
 
-    @abstractmethod
-    def newest(self, branch: Optional[str] = None) -> 'Version':
+    @abc.abstractmethod
+    def newest(self, branch: str = None) -> 'Version':
         """The newest version in the parent repository which has this one as an ancestor.
 
         Args:
@@ -78,8 +78,8 @@ class Version(ABC):
         """
         pass
 
-    @abstractmethod
-    def last_change_on(self, filename: str) -> Optional['Version']:
+    @abc.abstractmethod
+    def last_change_on(self, filename: str) -> typing.Optional['Version']:
         """Return the last version which changed the given file, looking back from this version.
 
         Returns: