Last week I got myself into a complete git merge and rebase nightmare. It’s not all that unusual now that I’m using Git in the context of a team where we have multiple developers and branches at various steps removed from the master. I often feel that working with Git is like riding a one of those Bucking Broncos - I feel totally fine until someone turns the speed dial.

Attempting to fix my errors just became a circular horror and it was suggested that I should just create a new branch off master and reapply my changes.

I had made many, many changes over the last few days and was visualising the pain of copying over all my changed files to notepad so I could one by one reapply these edits to the new branch.

Thankfully my boss was there to educate me on the use of git diff and patch - it was a revelation and probably saved me a day of copy pasting.

What is a Git Diff

For each file committed, Git stores an instruction explaining how to transform from the previous state to the current state. That might be delete line 2 from old version of file and replace with ‘brand new whizzy code’ from the new version of the file.

Try here for a more detailed explanation on Git Diff

Manually applying a diff file as a patch to new Git Branch

If you need to resolve a git merging/rebasing nightmare you could choose to create a diff file and then apply this as a patch to a clean branch.

First you need to ensure you have committed the changes in your working branch that you wish to keep. Then checkout master and pull any remote changes to ensure your local version of master is up to date.

  • git checkout master
  • git pull origin master

Create a diff file that records the line by line changes between the two branches.

NB. The order of the branch names is important.

The first instruction outputs the difference to the terminal so you can confirm the order. When you have confirmed this is correct you can output to a file.

  • git diff master..branch_name
  • git diff master..branch_name > descriptive_filename.diff

You can open this diff file in your normal text editor and delete any changes that you don’t want to apply. Just ensure you delete the entire diff section.

Here’s an example of a diff file:

diff --git a/api_utils/structure.py b/api_utils/structure.py
index 48071c0..221b80c 100644
--- a/api_utils/structure.py
+++ b/api_utils/structure.py
@@ -18,8 +18,8 @@ object_record_fields_only = ['systemNumber', 'accessionNumber', 'objectType', 't
                              'contentOther', 'contentConcept', 'contentLiteraryRefs', 'galleryLabels',
                              'partNumbers', 'accessionNumberPrefix', 'accessionNumberNum',
                              'accessionYear', 'otherNumbers', 'copyNumber', 'editionNumber',
-                             'aspects', 'assetsAll', 'recordModificationDate', 'recordCreationDate',
-                             'images']  # almost unadulterated
+                             'aspects', 'recordModificationDate', 'recordCreationDate',
+                             'images', 'assets']  # almost unadulterated

 
diff --git a/handler/objects/__init__.py b/handler/objects/__init__.py
index 3a1d6e4..96d1875 100644
--- a/handler/objects/__init__.py
+++ b/handler/objects/__init__.py
@@ -417,6 +417,7 @@ class Object(Document):
     year = Text()
     floors = Keyword(multi=True)
     anglesAll = Keyword(multi=True)
+    angles = Keyword(multi=True)
     refs = Keyword(multi=True)
     imagesAll = Keyword(multi=True)  # renaming original images field
     pages = Text(multi=True, fields={'raw': Keyword()})

The red block shows what will be removed from the first mentioned branch (in my case master) the green will be added to master.

Now you have the edited diff file, you can checkout a new clean branch from the latest master and apply the differences as a patch.

  • git checkout -b brand_new_branch_name

The first patch command outputs the proposed action to the terminal.

  • patch -p1 --dry-run < descriptive_filename.diff

If it looks good you can remove the dry run instruction and apply the patch.

  • patch -p1 < descriptive_filename.diff

Now you are free to commit and merge with the code in the master branch.