Is it possible to move/rename files in Git and maintain their history?
I would like to rename/move a project subtree in Git moving it from
/project/xyz
to
/components/xyz
If I use a plain git mv project components
, then all the commit history for the xyz project
gets lost. Is there a way to move this such that the history is maintained?
Git detects renames rather than persisting the operation with the commit, so whether you use git mv
or mv
doesn't matter.
The log command takes a --follow
argument that continues history before a rename operation, ie, it searches for similar content using the heuristics:
http://git-scm.com/docs/git-log
To lookup the full history, use the following command:
git log --follow ./path/to/file
It is possible to rename a file and keep the history intact, although it causes the file to be renamed throughout the entire history of the repository. This is probably only for the obsessive git-log-lovers, and has some serious implications, including these:
Now, since you're still with me, you're a probably solo developer renaming a completely isolated file. Let's move a file using filter-tree
!
Assume you're going to move a file old
into a folder dir
and give it the name new
This could be done with git mv old dir/new && git add -u dir/new
, but that breaks history.
Instead:
git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD
will redo every commit in the branch, executing the command in the ticks for each iteration. Plenty of stuff can go wrong when you do this. I normally test to see if the file is present (otherwise it's not there yet to move) and then perform the necessary steps to shoehorn the tree to my liking. Here you might sed through files to alter references to the file and so on. Knock yourself out! :)
When completed, the file is moved and the log is intact. You feel like a ninja pirate.
Also; The mkdir dir is only necessary if you move the file to a new folder, of course. The if will avoid the creation of this folder earlier in history than your file exists.
No.
The short answer is NO , it is not possible to rename a file in Git and remember the history. And it is a pain.
Rumor has it that git log --follow
--find-copies-harder
will work but it does not work for me, even if there are zero changes to the file contents, and the moves have been made with git mv
.
(Initially I used Eclipse to rename and update packages in one operation, which may have confused git. But that is a very common thing to do. --follow
does seem to work if only a mv
is performed and then a commit
and the mv
is not too far.)
Linus says that you are supposed to understand the entire contents of a software project holistically, not needing to track individual files. Well, sadly, my small brain cannot do that.
It is really annoying that so many people have mindlessly repeated the statement that git automatically track moves. They have wasted my time. Git does no such thing. By design(!) Git does not track moves at all.
My solution is to rename the files back to their original locations. Change the software to fit the source control. With git you just seem to need to git it right the first time.
Unfortunately, that breaks Eclipse, which seems to use --follow
.
git log --follow
Sometimes does not show the full history of files with complicated rename histories even though git log
does. (I do not know why.)
(There are some too clever hacks that go back and recommit old work, but they are rather frightening. See GitHub-Gist: emiller/git-mv-with-history.)
链接地址: http://www.djcxy.com/p/22654.html上一篇: 显示文件的历史记录?