Is it possible to move/rename files in Git and maintain their history?

前端 未结 14 2471
梦如初夏
梦如初夏 2020-11-22 04:42

I would like to rename/move a project subtree in Git moving it from

/project/xyz

to

/components/xyz

If I

14条回答
  •  长情又很酷
    2020-11-22 05:26

    While the core of Git, the Git plumbing doesn't keep track of renames, the history you display with the Git log "porcelain" can detect them if you like.

    For a given git log use the -M option:

    git log -p -M

    With a current version of Git.

    This works for other commands like git diff as well.

    There are options to make the comparisons more or less rigorous. If you rename a file without making significant changes to the file at the same time it makes it easier for Git log and friends to detect the rename. For this reason some people rename files in one commit and change them in another.

    There's a cost in CPU use whenever you ask Git to find where files have been renamed, so whether you use it or not, and when, is up to you.

    If you would like to always have your history reported with rename detection in a particular repository you can use:

    git config diff.renames 1

    Files moving from one directory to another is detected. Here's an example:

    commit c3ee8dfb01e357eba1ab18003be1490a46325992
    Author: John S. Gruber 
    Date:   Wed Feb 22 22:20:19 2017 -0500
    
        test rename again
    
    diff --git a/yyy/power.py b/zzz/power.py
    similarity index 100%
    rename from yyy/power.py
    rename to zzz/power.py
    
    commit ae181377154eca800832087500c258a20c95d1c3
    Author: John S. Gruber 
    Date:   Wed Feb 22 22:19:17 2017 -0500
    
        rename test
    
    diff --git a/power.py b/yyy/power.py
    similarity index 100%
    rename from power.py
    rename to yyy/power.py
    

    Please note that this works whenever you are using diff, not just with git log. For example:

    $ git diff HEAD c3ee8df
    diff --git a/power.py b/zzz/power.py
    similarity index 100%
    rename from power.py
    rename to zzz/power.py
    

    As a trial I made a small change in one file in a feature branch and committed it and then in the master branch I renamed the file, committed, and then made a small change in another part of the file and committed that. When I went to feature branch and merged from master the merge renamed the file and merged the changes. Here's the output from the merge:

     $ git merge -v master
     Auto-merging single
     Merge made by the 'recursive' strategy.
      one => single | 4 ++++
      1 file changed, 4 insertions(+)
      rename one => single (67%)
    

    The result was a working directory with the file renamed and both text changes made. So it's possible for Git to do the right thing despite the fact that it doesn't explicitly track renames.

    This is an late answer to an old question so the other answers may have been correct for the Git version at the time.

提交回复
热议问题