Git merge conflict to always take the newest file

后端 未结 4 1291
忘了有多久
忘了有多久 2020-12-09 21:04

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

相关标签:
4条回答
  • 2020-12-09 21:18

    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.

    0 讨论(0)
  • 2020-12-09 21:26

    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

    0 讨论(0)
  • 2020-12-09 21:32

    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.

    0 讨论(0)
  • 2020-12-09 21:37

    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
    
    0 讨论(0)
提交回复
热议问题