Repository: Qiskit/qiskit

Issue:
Allow versioning to include git information if not using released version
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?

Currently there is no way to distinguish between the master branch dev version and a final release version.  Currently, for example, they would both be labeled as `0.8.0`.

It would be nice to have unreleased (dev) versions tagged with the git repo commit that they are pulled from.  This is done, for example in SciPy and NumPy, and it quite easy to implement.



Discussion:
Something I have proposed in another issue related to requirements is to adopt the use of [pbr](https://docs.openstack.org/pbr/latest/) which will handle the dev versioning automatically for us (it just looks at git) and make a lot of other things automatic.

It also should work well with cython (because of #1789 this is something to think about) via: https://copyninja.info/blog/cython_setuptools.html
So in general I think we should not add dependencies unless really needed.  Although I am not sure what the "a lot of other things" you mentioned are, at least in this case, we can follow the SciPy and NumPy people and use a simple `git` call: https://github.com/scipy/scipy/blob/6db252d0105ba6fe3b23dd10d7a0da17dac0ce53/setup.py#L63

The Cython build in #1789 is already working, and does not need any additional tools (the linked article is three years old).
Well it would handle all the versioning for us, not just dev versions. We actually remove an explicit version string completely and it uses git to determine the version. So if we tag a commit that becomes the version, or it does dev versioning compliant with [PEP440](https://www.python.org/dev/peps/pep-0440/) Which removes the need for a version.txt file and an making sure we update everything (it can be manually overridden if necessary). Additionally it simplifies the requirements management in a similar way, just using requirements.txt, so we don't have to worry about forgetting to update it in 2 places. The metadata handling I find a bit simpler because it's done in a config file instead of code (but that's just my personal preference). It also will generate normal files for use like an authors list, a Changelog, and a manifest.in (by just looking at the files tracked in git). There's a high level overview of what it does here: https://docs.openstack.org/pbr/latest/user/features.html

As for the cython article I was just linking that to show it wouldn't break our cython usage by switching. Not that it was a requirement for adding it.
That being said I'm not tied to using pbr we can easily embed something like what you linked from scipy in the setup.py. I just think the benefits pbr provides is worth adding an extra dep (it's why I use it on almost all my personal projects).

Resolving patch:
diff --git a/qiskit/providers/basebackend.py b/qiskit/providers/basebackend.py
--- a/qiskit/providers/basebackend.py
+++ b/qiskit/providers/basebackend.py
@@ -20,7 +20,7 @@
 
 from abc import ABC, abstractmethod
 
-from qiskit.version import __version__
+from qiskit.version import VERSION as __version__
 from .models import BackendStatus
 
 
diff --git a/qiskit/version.py b/qiskit/version.py
--- a/qiskit/version.py
+++ b/qiskit/version.py
@@ -20,13 +20,70 @@
 
 
 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def _minimal_ext_cmd(cmd):
+    # construct minimal environment
+    env = {}
+    for k in ['SYSTEMROOT', 'PATH']:
+        v = os.environ.get(k)
+        if v is not None:
+            env[k] = v
+    # LANGUAGE is used on win32
+    env['LANGUAGE'] = 'C'
+    env['LANG'] = 'C'
+    env['LC_ALL'] = 'C'
+    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE, env=env,
+                            cwd=os.path.join(os.path.dirname(ROOT_DIR)))
+    out = proc.communicate()[0]
+    if proc.returncode > 0:
+        raise OSError
+    return out
+
+
+def git_version():
+    """Get the current git head sha1."""
+    # Determine if we're at master
+    try:
+        out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
+        git_revision = out.strip().decode('ascii')
+    except OSError:
+        git_revision = "Unknown"
+
+    return git_revision
+
+
 with open(os.path.join(ROOT_DIR, "VERSION.txt"), "r") as version_file:
-    __version__ = version_file.read().strip()
+    VERSION = version_file.read().strip()
+
+
+def get_version_info():
+    """Get the full version string."""
+    # Adding the git rev number needs to be done inside
+    # write_version_py(), otherwise the import of scipy.version messes
+    # up the build under Python 3.
+    full_version = VERSION
+
+    if not os.path.exists(os.path.join(os.path.dirname(ROOT_DIR), '.git')):
+        return full_version
+    try:
+        release = _minimal_ext_cmd(['git', 'tag', '-l', '--points-at', 'HEAD'])
+    except Exception:  # pylint: disable=broad-except
+        return full_version
+    git_revision = git_version()
+    if not release:
+        full_version += '.dev0+' + git_revision[:7]
+
+    return full_version
+
+
+__version__ = get_version_info()
 
 
 def _get_qiskit_versions():
     cmd = [sys.executable, '-m', 'pip', 'freeze']
-    reqs = subprocess.check_output(cmd)
+    reqs = _minimal_ext_cmd(cmd)
     reqs_dict = {}
     for req in reqs.split():
         req_parts = req.decode().split('==')


Test patch: