Search code examples
gitgit-merge

Git merge conflict to always take the newest file


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.


Solution

  • 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