Making git format-patch follow renames like git log --follow

后端 未结 3 1895
夕颜
夕颜 2021-01-03 03:15

I am trying to move files from one local git repository to another local git repository for a different project while preserving history fr

3条回答
  •  独厮守ぢ
    2021-01-03 03:47

    Yuck. I think the problem is some broken logic. In particular, when you combine --reverse and --follow you must specify the old file name:

    [rename foo to bar]
    $ git log --follow bar  # works
    $ git log --follow --reverse -- foo # requires "--" because foo is not in HEAD
    

    This ... sort of works. Except, it then treats the file as deleted when it hits the rename, and everything stops there.

    tree-diff.c contains this function:

    static void try_to_follow_renames(...)
    {
            ...
            /* Remove the file creation entry from the diff queue, and remember it */
            choice = q->queue[0];
            q->nr = 0;
    

    which is called if diff_might_be_rename returns true:

    static inline int diff_might_be_rename(void)
    {
            return diff_queued_diff.nr == 1 &&
                    !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one);
    }
    
    ...
    int diff_tree_sha1(...)
    {
            ...
            if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
    

    I'm making some large assumptions here, but when you go in the other order, instead of "file bar was just created, let's see if we can find a foo from which it was renamed", if the log is reversed you need to have "file foo deleted, let's see if we can find a bar to which it was renamed", and that's just ... missing, if the comment is accurate.

    If you have a lot of these to do, I'd suggest attempting to add something here to remember if the diff is reversed (as it is for both format-patch and log --reverse) and change the diff_might_be_rename() and try_to_follow_renames() code as needed.

    If you just have one, well, manually hacking up some diffs is probably easier. :-)

提交回复
热议问题