Skip to content

Instantly share code, notes, and snippets.

@mplewis
Last active December 30, 2016 09:10
Show Gist options
  • Save mplewis/0fcceba6b7a343f488d9 to your computer and use it in GitHub Desktop.
Save mplewis/0fcceba6b7a343f488d9 to your computer and use it in GitHub Desktop.

git-merge-android-manifest

Git merge strategy for Android Manifest files. See main() for more info.

matt@mplewis.com, created 2015-03-27

License: The MIT License


To use:

  • Add this script to your path
  • Install bzrlib:
pip install bzrlib
  • Add this to .git/config or ~/.gitconfig:
[merge "android-manifest"]
    name = Android Manifest merge driver
    driver = git-merge-android-manifest %O %A %B
    recursive = text
  • Add this to .gitattributes (use the correct path to your project's manifest):
    app/src/main/AndroidManifest.xml merge=android-manifest
  • Merge simply and with much happiness!

Thanks to github.com/mezis for git-merge-po.sh.

#!/usr/bin/env python
"""
git-merge-android-manifest
matt@mplewis.com, created 2015-03-27
License: The MIT License
Git merge strategy for Android Manifest files. See main() for more info.
To use:
- Add this script to your path
- Install bzrlib:
pip install bzrlib
- Add this to .git/config or ~/.gitconfig:
[merge "android-manifest"]
name = Android Manifest merge driver
driver = git-merge-android-manifest %O %A %B
recursive = text
- Add this to .gitattributes (use the correct path to your project's manifest):
app/src/main/AndroidManifest.xml merge=android-manifest
- Merge simply and with much happiness!
Thanks to github.com/mezis for git-merge-po.sh:
https://gist.github.com/mezis/1605647
"""
from bzrlib import merge3
import sys
import re
def main():
"""
Git merge strategy for AndroidManifest.xml files.
Take in paths to files to merge:
git-merge-android-manifest $ancestor $mine $theirs
If there are conflicts in the Android version code, it selects the one with
the highest integer version code. Other conflicts are left in the file
as-is for the user to resolve.
Save the data to $mine and exit cleanly if there are no other conflicts.
"""
filenames = sys.argv[1:]
filedata = []
for filename in filenames:
with open(filename) as f:
filedata.append(f.readlines())
ancestor, mine, theirs = filedata
conflicts_present = False
lines = []
m3 = merge3.Merge3(ancestor, mine, theirs)
for r in m3.merge_groups():
type, results = r[0], r[1:]
if type == 'conflict':
attempts = results[1:]
resolved, selected_lines = resolve_conflict(attempts)
if not resolved:
conflicts_present = True
else:
selected_lines = results[0]
for line in selected_lines:
lines.append(line)
final = ''.join(lines)
mine_name = filenames[1]
with open(mine_name, 'w') as f:
f.write(final)
if conflicts_present:
sys.exit(1)
sys.exit(0)
def resolve_conflict(attempts):
"""
If the conflict contains an android:versionCode tag, pick the attempt with
the highest version code.
Otherwise, merge the two attempts into a conflict section with markers
(>>>>>>>, =======, <<<<<<<).
Returns a tuple: (resolved, lines)
resolved: true if the conflict was resolved via version code tag
lines: a new list of lines for the conflicting section
"""
VERSION_CODE_REGEX = 'android:versionCode="([0-9]+?)"'
selected_attempt = None
selected_version = None
for attempt in attempts:
for line in attempt:
found = re.search(VERSION_CODE_REGEX, line)
if found:
try:
version_code = int(found.group(1))
except TypeError:
pass
if not selected_version or version_code > selected_version:
selected_attempt = attempt
selected_version = version_code
resolved = True
if not selected_attempt:
resolved = False
selected_attempt = conflict_markers(attempts)
return resolved, selected_attempt
def conflict_markers(attempts):
"""Append conflict markers to two conflict resolution attempts."""
mine, theirs = attempts
lines = []
lines.append('<<<<<<< MINE\n')
for line in mine:
lines.append(line)
lines.append('=======\n')
for line in theirs:
lines.append(line)
lines.append('>>>>>>> THEIRS\n')
return(lines)
if __name__ == '__main__':
main()
@scottmeng
Copy link

in macOS, I managed to install bzr by pip install bzr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment