Apply git diff/patch multiple times

2019-08-13 18:24发布

Using git flow I create a new branch, newFunction, off of develop branch. I add newFunction to example class:

class ExampleClass
{

    public function exampleFunction(){
        return "example";
    }

    public function newFunction(){
        return "new";
    }

}

Lets say I merge it to develop, I come back a few months later and my class looks like this.

class ExampleClass
{

    public function exampleFunction(){
        return "example";
    }

    public function anotherFunction(){
        return "another";
    }

    public function yetAnotherFunction(){
        return "yetAnother";
    }

    public function newFunction(){
        return "new";
    }

}

Is it possible to apply the diff between develop and newFunction at that point in time? Possibly using git patch or some sort of black magic. So I run a magical git something command and I end up with something like this:

class ExampleClass
{

    public function exampleFunction(){
        return "example";
    }

    public function anotherFunction(){
        return "another";
    }

    public function yetAnotherFunction(){
        return "yetAnother";
    }

    public function newFunction(){
        return "new";
    }

    public function newFunction(){
        return "new";
    }
}

and if I did it again, I would get this:

class ExampleClass
{

    public function exampleFunction(){
        return "example";
    }

    public function anotherFunction(){
        return "another";
    }

    public function yetAnotherFunction(){
        return "yetAnother";
    }

    public function newFunction(){
        return "new";
    }

    public function newFunction(){
        return "new";
    }

    public function newFunction(){
        return "new";
    }   
}

etc. I am aware that the code it currently generates is incorrect, as in the functions have the same name. I would use this for generation of boilerplate code in a legacy system, for example.

1条回答
再贱就再见
2楼-- · 2019-08-13 19:03

Answer

I think the command you are looking for is git apply. Assuming that the last commit on the newFunction branch only adds the four lines for newFunction you could apply the same change on the develop branch with the following commands:

git checkout develop
git diff newFunction^ newFunction | git apply --3way
# "newFunction^" means the second last commit on newFunction branch

Git apply will here attempt to apply the same change that was done in the last commit on the newFunction branch onto the develop branch.

When testing with a test repository adding one function for each commit, the above git apply did not apply cleanly. But when using three way mode it will leave the result open for manual resolve, e.g. git status will show both modified for the file and git ls-files -u will show something like

100644 21ecaba537582661c82c9dd2dff920a88a4b69a1 1   file.php
100644 56728941868d309cc06a49a8c49afc72cb0285b7 2   file.php
100644 0bbcab178802667c0228e424ce84f4c13a2b4c94 3   file.php

Additional tip on handling merge conflicts

The default git behaviour is to insert some text markers for the merge conflicts part which I find very hard to work with. I much rather like to merge graphically using KDiff3, and armed with the output from ls-files we can fetch all the relevant versions and create files with corresponding content which we run kdiff3 on. E.g.

$ git cat-file blob 21ecaba537582661c82c9dd2dff920a88a4b69a1 > file1.php
$ git cat-file blob 56728941868d309cc06a49a8c49afc72cb0285b7 > file2.php
$ git cat-file blob 0bbcab178802667c0228e424ce84f4c13a2b4c94 > file3.php
$ kdiff3 -o file_merged.php file1.php file2.php file3.php
$ mv file_merged.php file.php
$ git add file.php
$ git commit -m "Manually resolved git apply result"

With two manual diff alignments it is not difficult to resolve:

KDiff3 screenshot

Personally I have created a script that at its core does the above commands to resolve git conflicts, although a bit more sophisticated, and I use it all the time, I love kdiff3.

查看更多
登录 后发表回答