cytrinox
cytrinox

Reputation: 1946

Show git last commit hash and current branch/tag in flutter app

How can I access the last git commit hash, current branch and last tag from the source directory, when building a flutter app? I want to display this in a "About version" dialog.

There is https://pub.dev/packages/package_info but it has no information about git.

Are there any other packages that may provide this information?

Upvotes: 10

Views: 4668

Answers (5)

andrew-e
andrew-e

Reputation: 732

If we adjust Anton's Answer, by also adding pubspec.yaml to the asset bundle, we can generate an app version ID like 1.2.3+4-a1b2c3d4:

Future<String> getVersion() async {
  String gitVersion;
  final pubspecVersion =
      loadYaml(await rootBundle.loadString("pubspec.yaml"))["version"];
  var head = await rootBundle.loadString('.git/HEAD');
  if (head.startsWith('ref: ')) {
    final branchName = head.split('ref: refs/heads/').last.trim();
    gitVersion = await rootBundle.loadString('.git/refs/heads/$branchName');
  } else {
    gitVersion = head;
  }
  return "$pubspecVersion-${gitVersion.substring(0, 8)}";
}

Upvotes: 0

Anton Engelhardt
Anton Engelhardt

Reputation: 31

The Answer from Rithvik Nishad worked for me but with small modifications. I have to make a new answer because i cannot comment due to reputation.

The changes are needed because

  • our App is built in the CI (which does not have the ORIG_HEAD-file in the .git/ folder)
  • we wanted the currently checked out commit hash to be displayed and not the most recent remote one (which is what ORIG_HEAD actually resembles)

So here are the changes:

  1. Do not import .git/ORIG_HEAD in pubspec.yaml, the rest can stay
  2. Use this modified function to get the commit of the currently checked out head:
Future<String> getGitInfo() async {

  // Get the current head
  final head = await rootBundle.loadString('.git/HEAD');

  // Extract the branch name if needed

  if (head.startsWith('ref: ')) {
    // checked out branch name
    final branchName = head.split('ref: refs/heads/').last.trim();
    return await rootBundle.loadString('.git/refs/heads/${branchName}');
  } else {
    // HEAD points to a specific commit
    return head;
  }
}

  1. Then access it from wherever you need it.

Upvotes: 2

Rithvik Nishad
Rithvik Nishad

Reputation: 565

It may not be the best solution, but here's how I did it.

1. Add the necessary files to assets

flutter:
  assets:
    - .git/HEAD         # This file points out the current branch of the project.
    - .git/ORIG_HEAD    # This file points to the commit id at origin (last commit id of the remote repository).
    - .git/refs/heads/  # This directory includes files for each branch that points to the last commit id (local repo).

Default Gradle configuration excludes .git folder from builds, therefore this rule must be removed. To do this, add the following to your settings.graddle:

import org.apache.tools.ant.DirectoryScanner

DirectoryScanner.removeDefaultExclude('**/.git')
DirectoryScanner.removeDefaultExclude('**/.git/**')

2. Consume it from your .dart code

Future<String> getGitInfo() async {
  final _head = await rootBundle.loadString('.git/HEAD');
  final commitId = await rootBundle.loadString('.git/ORIG_HEAD');

  final branch = _head.split('/').last;

  print("Branch: $branch");
  print("Commit ID: $commitId");

  return "Branch: $branch,  Commit ID: $commitId";
}

3. Display it in your flutter app if needed

FutureBuilder<String>(
  future: getGitInfo(),
  builder: (context, snapshot) {
    return Text(snapshot.data ?? "");
  },
)

Expected output:

enter image description here

Note that hot reload works also for assets, so it should show changes.

Upvotes: 17

Noland
Noland

Reputation: 740

My method that doesn't need other packages, env vars, or adding and reading assets. And supports flutter project being in any child directory. Just directly write a .dart file with the post-commit git hook:

# post-commit
FILE="app/lib/such/a/deep/tree/settings/git.dart"
echo "// AUTO GENERATED FILE BY GIT HOOK post-commit" > $FILE
echo "const String GIT_COMMIT = '$(git rev-parse HEAD)';" >> $FILE
echo "const String GIT_BRANCH = '$(git rev-parse --abbrev-ref HEAD)';" >> $FILE

Then:

import 'package:fluffy-squirrel/settings/git.dart';

print(GIT_BRANCH);

This is how I ensure my Sentry instance always has the right release.

Upvotes: 5

khoibv
khoibv

Reputation: 369

Rithvik Nishad's answer does not work for me, because my flutter project is a child project and cannot access .git/ directory. For example:

root/
|__.git/
|__client/
|_____flutter project/  <== can not access to .git/ from here

So my solution is using a small script to get git info and save into the .env file

#!/bin/bash
set -e

branch=`git rev-parse --abbrev-ref HEAD`
escaped_branch=$(printf '%s\n' "$branch" | sed -e 's/[\/&]/\\&/g')
commit=`git rev-parse --short HEAD`

# branch
if grep -q 'GIT_BRANCH=' .env; then
    sed -i '' "s/^GIT_BRANCH.*/GIT_BRANCH=$escaped_branch/g" .env
else
    echo "GIT_BRANCH=$branch" >> .env
fi

# commit hash
if grep -q 'GIT_COMMIT=' .env; then
    sed -i '' "s/^GIT_COMMIT.*/GIT_COMMIT=$commit/g" .env
else
    echo "GIT_COMMIT=$commit" >> .env
fi

then read the .env file to get git branch/hash, ... (i'm using dotenv to read the file)

final gitBranch = dotenv.env['GIT_BRANCH'] ?? ''; // => features/change-logo
final gitCommit = dotenv.env['GIT_COMMIT'] ?? ''; // => 45a97d3

Here is my result:

Git info

Upvotes: 0

Related Questions