How can I make a git conflict ALWAYS get resolved by taking the newest file (latest changed timestamp), completley without a prompt?
I am building a syncscript with git backend, and I never want to actually merge a file, just override all older copies with the one that was edited/deleted/added last.
Edit: With newest file, I mean newest commit containing开发者_运维知识库 that file.
I came up this little merge driver that does what I want. For my purpose it is hard coded to the "master" branch and to the "origin" remote. I do not know how to make these parts dynamic.
#!/usr/bin/env sh
if git merge-file -p -q "$2" "$1" "$3" > /dev/null;
then git merge-file "$2" "$1" "$3";
else
MINE=$(git log --format="%ct" --no-merges master -1);
THEIRS=$(git log --format="%ct" --no-merges origin/master -1);
if [ $MINE -gt $THEIRS ];
then git merge-file -q --ours "$2" "$1" "$3";
else git merge-file -q --theirs "$2" "$1" "$3";
fi
fi
In short I look for the last commit with git-log that was not a merge, formatted as UNIX timestamp, then I compare them and run a custom git-merge with eiter ours or their version.
As a little bonus, it first makes a check to see if it is possible to merge the file without conflict. If that is possible, it merges both files.
I think you will have to write your own merge-driver for this. See "git help gitattributes", the "Defining a custom merge driver" sections for details on how to do just that.
Based on @Lilleman answer which is good but has a bug: if a file is modified on local master which is older than origin/master the expected behaviour is to pick origin/master but if you add a commit on top of local master it will pick the local (older version) of the file. git log needs to be executed with an extra argument which is the file path.
here a better version including variable branch names it's a bit hacky but it works
merge
#!/bin/sh
cd `findup .git`
PATH=$PATH:$( dirname "${BASH_SOURCE[0]}" )
HEAD=`git rev-parse --abbrev-ref HEAD`
echo "* merge=newest" > .gitattributes
sed -ie '/merge "newest"/,+2d' .git/config
echo "[merge \"newest\"]" >> .git/config
echo -e "\tname = Merge by newest commit" >> .git/config
echo -e "\tdriver = git-merge-newest %O %A %B %L %P $HEAD $1" >> .git/config
git merge $1
sed -ie '/merge "newest"/,+2d' .git/config
rm .gitattributes
cd -
git-merge-newest
#!/bin/sh
if git merge-file -p -q "$2" "$1" "$3" > /dev/null;
then git merge-file "$2" "$1" "$3";
else
MINE=$(git log --format="%ct" --no-merges "$6" -1 $5);
THEIRS=$(git log --format="%ct" --no-merges "$7" -1 $5);
if [ $MINE -gt $THEIRS ]; then
git merge-file -q --ours "$2" "$1" "$3" >/dev/null
else
git merge-file -q --theirs "$2" "$1" "$3">/dev/null
fi
fi
findup used
#!/bin/sh
pwd="`pwd`"
start="$pwd"
while [ ! "$pwd" -ef .. ]; do
[ -e "$1" ] && echo -n "$pwd" && exit
cd .. || exit 1
pwd="`pwd`"
done
exit 1
If anyone came here searching for a solution to avoid resolve conflicts arose from automatically generated files such as package-lock.json
, pubspec.lock
, *.pbxproj
, then you can create a .gitattributes
file defining a merge strategy
package-lock.json merge=union
See more info on git attributes
精彩评论