A step by step tutorial for keeping history in git while doing certain actions like moving or splitting a file
C# HTML CSS JavaScript
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
Git.History.Web
assets
.gitignore
Git.History.Web.sln
README.md

README.md

git-history

Introduction and purpose

This repository tries to explain and show at the same time how you can move and/or split a file under GIT and still keep all the history.

These actions are very common in projects where following certain guidelines requires to move things arround but at the same time keep all the history.

Examples are presented using Visual Studio 2015 IDE and Git CLI

Abstract

Move a file

These steps are advised to be taken when you do not have to change anything in a file, just move it, but as you would see in the second part, Edit and move a file the outcome is identical.

Moving a file is quite easy and there are two methods to accomplish it:

Copy-Paste the file from Source to Destination(works also with drag-and-drop)

Pre drag-and-drop

Pre drag-and-drop

Post drag-and-drop

Pre drag-and-drop

Staged changes

Staged changes

History after check in

History after check in

Run git cli command

git mv source_file destination_file

A good example would be the following command that moves the file from Helpers to Filters folder as we did with drag-and-drop:

git mv Git.History.Web\Helpers\MovableSecurityHelperV5.cs Git.History.Web\Filters\MovableSecurityHelperV5.cs

Running the following command will inform you of the movement changes

git status

Git status

From this point, we can just commit and check the history of the moved file as described above

Edit and move a file

All the steps described above apply here as well. The only addition to this part is the fact that editing the moved file will have the same result.

If you only have to move and edit a file, perform the steps described above and also the additional edits you require.

Split a file

Preserving the history of a file while moving/editing it is pretty easy as we already saw.

Splitting a file into two while preserving the history on the both ends it's a whole different adventure which I'll describe bellow.

What exactly do we mean with splitting a file

Let's take the scenario in which a class contains two methods like the one below

public class MyFirstClass
{
   public void Method1()
   {
      ...
   }

   public void Method2()
   {
      ...
   }
}

And we want to move method Method1 into a different class, let's say MySecondClass, but preserve the history that it accumulated in MyFirstClass for all kinds of reasons

The outcome for which we want aim is the following

public class MyFirstClass
{
   public void Method1()
   {
      ...
   }
}

public class MySecondClass
{
   public void Method2()
   {
      ...
   }
}

Usual procedure - with no history

Usually, people tend to simply create a new destination file and copy over the implementation they need from the source file. This will make Git to track changes of this new destination file from the time it was created which is the time of the movement of the implementation.

This will result in the loss of all history for those bits of code which were moved from source to destination

The trick

  • The trick into preserving the history on both files is to create a new branch
  • We will have to move/edit the file in the newly created branch then merge it with the current one
  • This will create a conflict, but we will keep the new file from the new branch

Create 'split-helper-v5' branch

Create a new branch

Rename and Move file on 'master' branch

Rename and Move file on master branch

Switch to 'split-helper-v5' branch

Switch to new branch

Rename and Move file on 'split-helper-v5' branch

Rename and Move file on new branch

Switch to 'master' branch

Switch to master branch

Open command prompt on 'master' branch

Open command prompt on master branch

Run the merge command - be aware that mergeing directly from Visual Studio 2015 does not give the same results

git merge --no-ff split-helper-v5

Switch to master branch

Merge conflicts

Merge conflicts

Merge conflicts detailed

Merge conflicts detailed

Keep file from 'master' branch - this will ensure history for the file on the 'master' branch

Keep file from master branch

Keep file from 'split-helper-v5' branch - this will ensure history for the file on the 'split-helper-v5' branch and thus accomplish the split

Keep file from new branch

Leave deleted file from both branches - we do not need the file from the place it was moved in neither of the two branches

Keep file from new branch

Commit merge changes - don't bother the [add] status of the file

Keep file from new branch

'master' branch file history

Keep file from new branch

'split-helper-v5' branch file history

Keep file from new branch

Completing these steps will make you end up with two files which have the same history

You will still have to move them in their right place, if you haven't in the above steps. For that, follow the instruction presented in Move a file