Git Rebase VS. Merge

I’ve used git for version control for a good while now, but I’ve never really tried to understand the difference between merging and rebasing. I guess I’m a bit lazy that way, having a “If it works, it works” mentality. I’ve now spent some time figuring out the difference, and try making a short and understandable post about it.


The Difference

Both commands, git rebase and git merge, solves the same problem. Taking changes from one branch and integrating them into another. The difference happens in how changes are spliced together.

A typical use case is having a master and a feature branch. You want the changes from the master into the feature branch. Doing the git merge master command from the feature branch will create a new merge commit in your feature branch. A merge is basically a new commit, with two parents.

Git merge

Whereas, rebasing will put the feature branches’ changes onto the master branch. The git rebase master will effectively move the commits to the tip of the master branch. Another way of looking at it is that you are relocating the place where you branched out from master to a more recent place in master’s history. In addition, a rebase will for every commit in feature create a new identical commit on top of master.

Git rebase


Advantages and Disadvantages of Rebasing

  • Cleaner history that is easier to read.
  • Slightly harder than merging.
  • Rewrites the commit history. which might be problematic.
  • You can’t see when changes from master were incorporated into feature.
  • Gives you the ability to use interactive rebasing. You can remove intermediate backup commits and replace it with a single commit. You can also reword your commit messages.
  • Maybe the best way to incorporate changes another developer made on master onto your feature branch.


Advantages and Disadvantages of Merging

  • Merging is a non-destructive operation
  • Each merge creates a commit, which might clutter the branches’ history.
  • Traceability. You have a merge commit, which indicates that a convergence between two branches has taken place.

Finally, I would like to point out that the explanation above might be incorrect. It’s based on my current understanding of git. And I’m by no means a git wizard. Please read the references below to get a more thorough explanation.

Further Reading

Atlassian git tutorial
Stackoverflow answer
Blog post explaining the difference well

UV Mapping in Blender for Unity

Just learned how to do UV mapping in Blender, and thought I should write it down before I forget. Currently, I’m doing the Learn 3D Modelling course at Udemy. I’m now past the basic modelling stuff, and wanted some practice. I decided to do a chessboard, and yup, you guessed it, not that challenging since it’s basically a square shape. It does not look anything like a chessboard, without the checker pattern.

No texture

So I decided to try out UV map painting, to see if I could turn this nondescriptive shape into a bona fide chessboard.


UV Mapping in Blender Recipe

1. Adding Seams

  • The 3D model is complete and texturing is the next step. Your first step is to create seams to help Blender unwrap your model’s surface onto a flat plane. The plane area is where you’ll do the painting later on.
  • Enter edit mode <TAB>
  • Open the tools section in the left sidebar <T> of the 3D View
  • Pick edge select mode to select seams on your model.

Edge select

  • Select edges that you want to convert to a seam. A loop selection of edges will create a disconnected island, which is good, when organizing the UV map later on. Create several of these. For instance, the chessboard was split by 4 seams. Top, bottom and two of the sides.

Selection edges for seam

  • To create the seam, scroll down in the Shading/UVs section of the tools side panel, and make a seam when you are satisfied with an edge selection. You will find a button called Mark Seam.

UVs panel

  • After you’ve created some seams, select the entire model in edit mode by pressing <A>. Then, click Unwrap.Again, click Unwrap in the drop down which will appear immediately after.

Seams


2. Clean the UV Map

  • Open a UV/Image Editor View. You will probably see something similar to this:

UV map

  • To see if all the face sections are disconnected, use the island UV selection tool. Right click on each face and see if only that face section is highlighted.

Island UV selection tool

  • As you can see, two of the faces are still connected. To separate them select all the polygons of one section using the UV face selection tool and press the <Y> key. Use the grab tool <G> to see if the area is separated. More details here.

  • Then, reorganize the UV map by rotating, scaling and moving UV islands. The shortcuts are <R>, <S>, and <G> key, respectably.

Island UV selection tool


3. Create the Texture and UV Layout Image

  • Go to the Texture tab. Create a new texture.
  • Change Type from none to Image or Video
  • In the Image section, click new. Create a new image with width and height of 2048 and select a white color. Give it a sensible name. For instance, chessboardtex.
  • Then, in the Mapping section, change Coordinat to UV , and find the UV map in the Map drop down.
  • Go to the UV/Image Editor, select chessboardtex in the menu that appears after clicking the image icon in the toolbar. The white texture image will appear in the background of the UV map.

Select texture

  • The Image menu item now has an asterisk. This is because you have not saved the image yet. Use the Save As Image option.
  • If you want to do the UV paining in an external program, such as Photoshop or Gimp, you’ll probably want the UV layout as a reference when painting. Press UVs and in the menu, select Export UV layout.


4. UV Paining

  • Open an image editor (Photshop, Gimp or similar). Add the saved texture image and the UV layout image on top, in a new layer.

Before paining

  • Go wild painting. Below is my finished chessboard texture.

Before paining

  • In Blender’s UV/Image Editor, go Image and press Reload image, to see the updated texture on your 3D model.

5. Add Model to Unity

  • When you’re satisfied with the result you can save the model as a .blend file somewhere in the assets directory of your Unity project.

  • But where did the texture of the model go in Unity? Remember to copy the texture image into the Assets folder. You need to tell Unity to use the image for the model. I’m not sure if there is a better way of combining the texture and model into a single file, but the following seems to work fine.
  • Adjust the material settings on your model. For instance, pick the Mobile/Bumped Diffuse shader, and select the imported texture image under Base (RGB).

Before paining


You now have a textured model in Unity.

Further Reading

Separate vertices

Exporting & Editing UV Maps

Software Development Timesaver #3

Expanded build folder

If you’re on Windows computer and using Atom, you might have encountered this error in your terminal, when running gulp watch:

Error: EPERM: operation not permitted, unlink 'C:\user\equalpasta\somepath\project\build'

A Google search reveals that variations of this error are a common problem.

Why does this happen? How to fix it? One reason can be the Atom editor. Turns out having the build folder expanded in Atom can cause this. It seems like Atom locks the folder if expanded in the project view, when running gulp watch.

Minimize the build folder in Atom, and re-run ‘gulp watch’.

This solved the issue for me.

Vendor Bundle to Improve Gulp Build Speed

Since the previous post I’ve looked more into Gulp. I started migrating the tool website from the Express/React setup to use the static-react-starter project starter. The transition has worked fine so far, but I’ve realized some issues with the starter project.

  • Gulp watch is slow to rebuild when the number of JavaScript files and dependencies increase.
  • The resulting build structure is messy and results in urls that are long. Ideally I want a short path following the domain name.
  • Each page is relatively large in file size, since the JavaScript files are not uglified.

The build time quickly became annoying. To fix this, I tried replacing gulp.watch with watchify for the JS files. Watchify helps incrementally rebuilding your bundles while developing, and works together with browserify. This really helped speed up the script rebundling time. Before it could take anywhere from 5-10 seconds from saving a file to the update appeared in the browser. After the switch, it takes less than a second. However, the initial build time only improved marginally, if at all. After adding uglify to the script task, the initial build time was around 14 seconds.


Creating an External Vendor Bundle

What solved this problem for me, was creating a vendor script bundle in addition to each subpage’s app script bundle. This can be done by taking Browserify’s external and require options in use. The result was that each app script bundle would only take around 1 second to build, whereas the vendor script bundle takes around 5 seconds to build. Much faster!


Why you Should do This

  • You seldom update the dependencies of a project. Watching dependencies and building them more than once are unnecessary.
  • In my case, each subpage utilizes mostly the same dependencies. Having a common bundle for vendor scripts might reduce load time because of caching.
  • Improves the development workflow. Changes are propagated faster from the editor to your browser.
  • With gulp.parallel the app subpage script bundling task and the vendor bundle task are conducted in parallel.


Vendor Bundle with Gulp Recipe

Import Project Dependencies

Start by loading the dependencies into your Gulp file:

...
import packageJson from './package.json';

const dependencies = Object.keys(packageJson.dependencies || {});
...

The dependencies variable will contain a list of your project dependencies that you’ve added through npm install <dep> --save.

Modify your Script Bundler Gulp Task

You will need to tell Browserify about external requires. When Browserify encounters a require (or import) marked as external it will ignore it when building a bundle. Basically, it will trust you to add these dependencies through another script tag somewhere in your HTML.

...

let b = browserify(opts);
b.external(dependencies);
b.transform(babelify);

...

Create a Vendor Bundling Gulp Task

After modifying the app bundling task to ignore the dependencies, you’ll need to create a vendor script file. Create a new Gulp task:

export function vendorScripts() {
  return browserify()
  .require(dependencies)
  .bundle()
  .on('error', (err) => console.log(err))
  .pipe(source('vendor.js'))
  .pipe(buffer())
  .pipe(uglify({compress: {unused: false}}))
  .pipe(gulp.dest(dirs.dest + '/app'))
}

You will also have to include this new task in your build task:

...

const build = gulp.series(clean, gulp.parallel(styles, vendorScripts, scripts, images, sounds, views))
export { build }

...

Add new Script Tag

Somewhere in your HTML, above where the app bundle script is, include the vendor bundle script. For instance:

...

<script src="/app/vendor.js"></script>
<script src="/app/tool1/entry.bundle.js"></script>

...

If you go to Chrome’s Network tab in the inspect window, you can see both vendor.js and entry.bundle.js will be requested on page load.

To see the entire Gulp file, go here.