Notesheet: Parcel (JavaScript bundler)

Status: Work in Progress (Updated 04 March 2020)


What is Parcel? It’s basically webpack without all the configuration automatically handled out of the box so you can just install it and all your “modern” front-end development compilation happens automatically. Seriously, zero configuration. Clone my sample repository at https://github.com/jsnelders/sample-parcel-js, follow the instructions in the readme.md file and see for yourself.

(That being said, further reading indicates webpack 4 is also zero configuration, though to date I haven’t found a tutorial that doesn’t touch the webpack.js file.)

I discovered Parcel today (11 Feb 2020) and had a test site up and running in under 5 minutes, including typos. Compared to webpack which took “I don’t know how long” to get setup.

  • Keep in mind I’m focused on front-end web development and basically just need it for transpiling ES2015+ to ES5, SCSS pre-processing, minification, bundling and cache busting. And I want the whole setup to be simple.
  • The official site https://parceljs.org/ has a easy getting started guide.
  • The official guide and some articles say you need to npm install the “sass” package but in my sample site this worked out of the box. I suspect that’s because I’m using a version with included features greater than the documentation suggests.

Update after 3 weeks:

  • For the most part it’s working well.
  • It updates packages.json and installs dependencies based on my code without me needing to think about it.
    • One initial hitch was referencing images in Vue.js. Bit after a bit of research I found you can use a JavaScript import like import rootImages from "./images/*.*";, then in your JavaScript you just use rootImages.{your_image_name_in_that_folder}.{image_extension} to reference an image (the value will point to the image path in the distribution/build folder.
      I actually created a new JavaScript module file that includes the import and exposes the images. That way, if I switch back to webpack or some other system, I’ve encapsulated all image dependencies in the once location. Following the the complete code from my file to show what I’ve done:

      import rootImages from "./images/*.*";          // Import to reference Parcel.js generated images.
      import w3images from "./images/w3images/*.*";   // Import to reference Parcel.js generated images.
      // Search: "parcel js copy images" and "parcel js references images in javascript"
      //      https://github.com/parcel-bundler/parcel/issues/1411
      //      https://github.com/parcel-bundler/parcel/issues/3056
      export const assets = {
          images: {
              root: rootImages,
              w3: w3images,
          }
      };
      

      Now I reference [for example] assets.images.root.{file}.{extension} to get the actual path to a file.

  • I have noticed sometimes I’ll create a syntax error (or some other error) while refactoring and I can’t get rid of errors in the browser console. Even a hard refresh doesn’t work. Stop parcel on the command-line then restart it – that usually fixes the issue, or at least generates a new error on the parcel command-line that points me in a better direction to the error.
  • I’m still using parcel in a private SaaS project I’m building. Sometimes I feel the urge to move over to webpack for better errors and debugging, but I’m familiar enough with it now I don’t switch. By moving parcel dependencies to their own JS modules I can still do it in the future with relative ease.

Resources

Notesheet: Webpack

Status: Work in Progress. Updated: 7 February 2020


Points of Interest

 

 


Resources

Notesheet: Babel (JavaScript)

Status: Work in Progress. Updated: 7 February 2020


Installation

  • npm install --save-dev @babel/core @babel/cli @babel/preset-env. Install locally in your project and add it as a dev only dependency.
  • Add a .babelrc file to the root of your project. This is the Babel configuration file.
    {
      presets: ['@babel/preset-env']
    }
    
    or
    
    {
      "presets": [
        [
          "env",
          {
            "targets": {
              "browsers": ["last 2 versions", "safari >= 7"]
            }
          }
        ]
      ]
    }
  • Create a “source” directory (and sub-directories) when all source files live (e.g. “src”, “src/js”, “src/css”, etc). In my examples it’s src.
  • Create a “build” directory where all your compiled/transpiled and ready to use files are placed (e.g. “dist”, “build”, “public”). In my examples it’s dist.

 

Running with NPM

  • Create an NPM “script” to run it (will have to be run manually. Eg:
    "scripts": {
      "build": "babel src -d dist"
    },
  • Run npm run build on the command-line and Babel will transpile all JavaScript under the “src” directory and produce output files in the “dist” directory.

 

Running with webpack

  • npm install webpack webpack-cli --save-dev – Install webpack and the CLI.
  • Add a “script” to npm’s packages.json:
    "scripts": {
      "build": "webpack --config webpack.config.js"
    },
  • Create a webpack.config.js in the root of the project
    const path = require("path");
    
    module.exports = {
      mode: 'development',
      entry: "./src/js/index.js",   // Note: "src" is the source directory name from above.
      output: {
        path: path.resolve(__dirname, "dist"),   // Note: "dist" is the build directory name from above.
      filename: "bundle.js"
      }
    };
  • Run npm run build to build files into the “dist” folder.
  • Install the Babel loader for npm install babel-loader babel-core --save-dev.
  • Add the following to your webpack.config.js file:
    module.exports = {
      // ... existing content is here ...
      
      module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
              loader: "babel-loader",
              options: {
                presets: ["@babel/preset-env"]
              }
            }
          }
        ]
      }
    };
  • “This uses a regex statement to identify the JavaScript files to be transpiled with the babel-loader, whilst excluding anything in the node_modules folder from that. Lastly, the babel-loader is told to use the babel-preset-env package installed earlier, to establish the transpile parameters set in the .babelrc file.” [src]
  • Run npm run build again.

 


Resources

 

Looking into:

Notesheet: JavaScript

Status: Work in Progress. Updated: 4 February 2020


Truthy & Falsy

 

Immediately-Invoked Function Expression (IIFE) (“iffy”)

  • Is an unnamed function (so no global scope pollution) that is executed as immediately after it is defined.
    • It can only be called once and not again later, because their is no name hanging on global scope to call.
  • All variables and functioned defined within an IFFE are in their own local/private scope.
  • It is also known as a Self-Executing Anonymous Function.
  • You can return a value from an IIFE and store the result in a variable.
  • You can also pass in arguments to the anonymous function.
  • What scenarios would you want to use an IIFE in real life (what’s an example)? I did work on a project once that used it, but can’t remember how it helped us.
  • https://developer.mozilla.org/en-US/docs/Glossary/IIFE

 

 

Scope

  • The context of execution.
  • The context in which values and expression can be referenced.
  • Global scope: In front-end web development this is the highest level (generally page level) and any variable or function defined in global scope can be access by another other function.
  • Local scope: Think of it as the scope contained within a function. Variables and nested functions defined within a function cannot be accessed by external functions.
    • A nested function can access variables and functions defined in parent (and ancestor) scope, but parents cannot access variables and functions defined in children.
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Variable_scope
  • https://www.w3schools.com/js/js_scope.asp

 

Lexical Scoping

  • Describes how a parser resolves variable names when functions are nested.
  • The word “lexical” refers to the fact that lexical scoping uses the location where a variable is declared within the source code to determine where that variable is available.
  • So, nested functions have access to variables declared in their outer scope.

 

Hoisting

  • Unlike other languages, in JavaScript you can define a variable (e.g. var myVariable;) in you code after you access it (set a value or read it).
  • In other languages trying to access a variable before you first define it will cause an “undefined variable” type error.
  • Hosting allows this later definition.
  • It “conceptually” moves (hoists) the definition of the variable to the top of the scope it is defined in, so it is already available when the lines that access it are executed.
  • JavaScript does not rearrange your code.
  • What happens is during code compilation the variables definitions (also function definitions) are found and loaded into memory at the top of their scope.
    • This scope can include Global Scope and Local Scope. Local scope may be the full scope of a function.
    • As of ES2015, variables defined with “let” can be hoisted to the top of their “block” level scope (the scope defined within a set of opening an closing curly braces (i.e. “{” and “}”). For example, within an if() or for() statement.
  • Then during the next phase – code execution – they are available.
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Variable_scope

 

Closures

  • In JavaScript a function can be defined within another function.
  • The inner function has access to variables in the scope of the outer function and other parent-of-parent (ancestor) functions.
  • Closure is the ability for the inner function to continue accessing the variables of the parent scope when it is being executed later.
    • i.e. the outer function returns the inner function (or an object containing the inner function) and that inner function is run some time later in code execution.
  • Each instance of the returned inner function has access to its own copy of the variables in parent scope.
  • It allows you create units of “closed” and re-usable functionality, with data (variables) that do no clutter global scope.
  • https://www.w3schools.com/js/js_function_closures.asp
  • https://developer.mozilla.org/en-US/docs/Glossary/Closure
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

 

Namespaces

 

 

 


Resources

Notesheet: ES6/ES2015+ (JavaScript)

Status: Work in Progress. Updated: 3 February 2020


Arrow Functions

  • Shorthand format for writing traditional functions.
  • Denoted by what some people call a “fat arrow”: =>
  • Removes the “function” keyword and often the “return” keyword and function block curly braces (“{” and “}”)
  • Formats can include:
    • () => { return …..; }
    • {x} => (return x+1; }
    • (x, y, z) => { if (x == 1} { return y; } else { return z; } }
    • Class.someFunction(x => x + 1);
    • var myFunction = x => x + 1;
    • var myFunction = x => { return x + 1; };
  • https://caniuse.com/#search=arrow%20functions

 

Traditional JavaScript function:

function sumOfNumbers(number1, number2)
{
  return number1 + number2;
}

 

ES2015 arrow function equivalent:

var sumOfNumbers = (number1, number2) => { var sum = number1 + number2; return sum * 2; }

 


Classes

Traditional “class” using a function

function Person(firstName, lastName)
{
  this.FirstName = firstName;
  this.LastName = lastName;

  this.GetFullName = function()
  {
    return this.FirstName + " " + this.LastName;
  }
}
var person = new Person("Bob", "Smith");
person.GetFullName();

ES2016 Class

class Person
{
  constructor(firstName, lastName) 
  {
    // FirstName and LastName properties are automatically created.
    this.FirstName = firstName;
    this.LastName = lastName;
  }
  
  /*
  *	Method to return the full name.
  */
  GetFullName() 
  {
    return this.FirstName + " " + this.LastName;
  }
}
var person = new Person("Jason", "Snelders");
person.GetFullName();

 

You can also define a property on the class like pre-ES2015, as in the following example.
Define it in the constructor() and you don’t have to pass a constructor parameter in to do anything with it (just give it a default value).
Then you can use the special “set” and “get” function to access it later. Or access it directly.
In this example “_displayName” is the defined property in question.
NOTE: You can’t use the same name for a property as the “set”/”get” function, so a good convention is to prefix the property with an underscore (“_”).
It’s still publicly accessible but represents a logically private property.

 

class User {
  constructor(username, password, loggedIn = false)
  {
    this.username = username;
    this.password = password;
    this.loggedIn = loggedIn;
    
    this._displayName = "";
  }

  set displayName(name) { this._displayName = name; }
  get displayName() { return this._displayName; }
  
  show()
  {
    console.log(`Username: ${this.username}`);
    console.log(`Password: ${this.password}`);
    console.log(`Logged In: ${this.loggedIn}`);
    console.log(`Display Name: ${this._displayName}`);
  }
}

// Create an object from the Class
const jason = new User("jason", "test123");

console.log("Show(1)...");
jason.show();

jason.displayName = "Jason Snelders";

console.log("Show(2)...");
jason.show();

jason._displayName = "Directly set _dislayName";

jason._displayName = "The Jason";

console.log("Show(3)...");
jason.show();

console.log(`Read directly from jason.displayName = '${jason.displayName}'`);

See it in action (open the Console) at https://codepen.io/jsnelders/pen/abOOGVe.

 


Define Variables: ‘let’ and ‘const (vs ‘var’)

  • Traditionally we only had ‘var’ keyword to define a variable.
  • ‘let’ is like ‘var’ but the variable is constrained to block scope – i.e. within the curly braces (“{” and “}”) it is defined between. For example, if() and for() statements.
  • ‘const’ is a constant with a value that is set at the time it is defined and that cannot be changes later.
    • The exceptions are:
      • arrays: values/elements within the array can be added and remove (but the whole array cannot be re-assigned).
      • objects: values of individual properties can be update, but the whole object cannot be reassigned.
  • https://caniuse.com/#search=let
  • https://caniuse.com/#feat=const

 

Simple var, let and const

var aVariable = "One";
const aConst = "Two"
let aLet = "Three"

console.log(aVariable);  // Display "One"
console.log(aConst);     // Display "Two"
console.log(aLet);       // Display "Three"
  
aConst = "Four";	 // No. You cannot change a constant. Will produce a "Assignment to constant variable" error.
  
aLet = "Five";
console.log(aLet); // Now displays "Five"

 

Scoping ‘let’

if (aVariable == "One")
{
  // A new variable 'aLet' is defined within only within the block scope of the if() statement.
  // It will not affect the value of 'aLet' defined above.
  let aLet = "New Let";
  
  console.log(aLet);	// Display "New Let".
}

// We cannot see the 'aLet' defined in the if() statement 
// so we display the value of 'aLet' defined in the out scope 
// (i.e. the original aLet).
console.log(aLet);	// Display "Three"

 

Arrays as constants

const array = [1, 2, 3];
  
console.log(arrayToString(array));  //Display 1,2,3
  
// We cannot do this - re-assign the array.
//array = [4,5,6];	
  
// But we can still add/remove individual items from the array.
array.push(7);
  
console.log(arrayToString(array));   // Display 1,2,3,7

 

Objects as constants

const person = {
  name: "Jason",
  age: "Old"
}
  
console.log(person.name);   // Display "Jason"
  
// We cannot re-assign the object (like the array).
//person = { name: "Bruce" };
  
person.name = "Bruce";
  
// But we can update individual properties on the object.
console.log(person.name);   // Display "Bruce"

 

Example: using ‘let’ in counters to preserve existing variables.

//-- Traditional variables
var i = "Cat";
  
console.log(i);   // Display "Cat"
  
for (var i = 0; i<=5; i++)
{
  // Do something
}
  
The original declaration of 'i' was re-purposed for the counter.
console.log(i);   // Display "5".
  

//-- ES2015 example with 'let'
  
let i = "Cat";
  
console.log(i);   // Display "Cat"
 
for (let i = 0; i<=5; i++)
{
  // Do something
  console.log(i);   // Will update and display increasing from "1" to "5" with each loop.
}
  
// The original definition of 'i' in the outer scope (outside the for() loop) is preserved.
console.log(i);   // Display "Cat".

 


Default Function Parameter Values

  • A default value can be specified on parameters in the definition (signature) of a function.
  • If the function is called and that parameter is missed, the default value will be used.
  • If a value is passed in to the parameter then the supplied value is used.
  • Parameters without default values must appear before the first default parameter.
    • e.g. This is wrong myFunction(param1, param2 = ‘some value’, param3) because param3 does not have a default value but it appears after a parameter that does have a default.
    • Why? Consider calling the function: myFunction(‘first value’, , ‘third value);. Having a blank parameter when calling a function is not not valid code.
  • https://caniuse.com/#feat=mdn-javascript_functions_default_parameters

 

Traditional function

function aboutMe(firstName, lastName, location)
{
  return "My name is " + firstName + " " + lastName + ". I come from " + location + ".";
}

// This will error because the 'location' parameter is not passed in.
var result = aboutMe("Jason", "Snelders");

 

ES2015 function with a default parameter value

function aboutMe(firstName, lastName, location = 'Woop Woop')
{
  return "My name is " + firstName + " " + lastName + ". I come from " + location + ".";
}

// The default value of "Woop Woop" will be used for 'location'.
var result1 = usingDefaultParameters("Jason", "Snelders");
console.log(result1);   // Display: My name is Jason Snelders. I come from Woop Woop.
  
// The provided value of "Melbourne" will be used for 'location'.
var result2 = usingDefaultParameters("Jason", "Snelders", "Melbourne");
console.log(result2); // Display: My name is Jason Snelders. I come from Melbourne.

 


Reset Operator in Function Parameters

Example function definition:

function myFunction(myName, ...roles) 
{ 
  console.log(roles); 
}

The 3 dots preceding ‘roles’ (…roles) is the rest operator.

So if we call the function:

myFunction("Jason", "Developer", "Architect", "Lead", "Consultant");

The console output of ‘roles’ from that function will be an array:

["Developer", "Architect", "Lead", "Consultant"]

 

 


Template Literals

  • A string surrounded by back ticks  (`).
  • The string can be split over multiple lines.
  • You can embed literal references to variables in the same scope that are replaced when the string is “rendered” (aka “variable/expression replacement” or “string interpolation”).
  • A good option for “+” operator based string concatenation.
  • Any expression in JavaScript can be used within the curly braces (“{…}”).
  • https://caniuse.com/#feat=template-literals
var name = "Jason";
var statement = `My name is ${name}`;

console.log(statement);   // Displays "My name is Jason"

var multilineStatement = `My name is ${name}
and I am a software developer`;

console.log(multilineStatement);   // Displays "My name is Jason
                                                and I am a software developer".

Alternative to concatenation:

Old style:

var createUrl = function(domain, path) { return "https://" + domain + "/" + path;  }

With string literals:

var createUrl = function(domain, path) { return `https://${domain}/${path}`;  }

 

Other expression examples

`2 + 2 = ${2 + 2}`
`It is ${new Date().getHours() < 12 ? 'AM' : 'PM' }`

 


Spread Operator (…)

Example:

const myArray = [1, 2, 3];
console.log(...myArray); // Displays "1 2 3" (the individual values of the array).

Example scenario:

function add = (a, b, c) => a + b + c;
const myArray = [1, 2, 3];
add(...myArray);  // Returns "7"

Using the spread operator splits myArray and assigned each of the value to the arguments of the add() function we are calling.

Another example – add arrays together:

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const array3 = [...array1, ...array2, 10];

This will create an array that looks like [1,2,3,4,5,6,10].

Similar Example with objects:

const obj1 = { name: "Jason" };
const obj2 = { location: "Melbourne" };
const obj3 = { ...obj1, ...obj2, "Learning": true };

We end up with an obj3 that l looks like:

const obj3 = { name: “Jason”, location: “Melbourne”, “Learning”: true };

And we can change obj1.name = “Bruce” and obj3.name remains as “Jason”.


Tagged Templates

  • Function that take a mix of string and variables, then formats and returns them based on some rules you apply.

 


Modules (“import” and “export”)

  • Code that can be written in one file and used in another (outside of the global scope).
  • Keywords “import” and “export”.
  • The name of the module is (by default) taken from the name of the .js file.
  • Each function we want to make available to other files is included in an “export”.
  • To use exported functions in other files we use the “import” keyword and reference the file to import from.
  • By default all exported functionality is imported, or we specify just the functions we want.
  • You can export a single default function (“export defailt …”) from a module and when importing you can give it any name you want.
  • NOTE: As of early 2020 modules is not handled well natively in Node (and I presume browsers) so you will need to use bundlers to get it working.

 

 


Other features to create examples for:

  • 22:34 Extended Literals
  • 24:42 Extended Object Literals
  • 28:18 Destructuring Assignment
  • Promises
  • async/await

 

 

 


Learning Resources

Notesheet: Node Package Manager (npm)

Updated: 31 January 2020

 

The npm website is: https://www.npmjs.com/.

Note: As npm evolves some commands may change or become deprecated. We’ve already seen this with v5 (–save is now added by default during npm install) and v5 (npm audit seems to have replaced nsp check). Such is the ways of software development.

This chaetsheet was created with front-end web development in mind.

 

Initialising

  • npm init: Asks questions to create a package.json file.
  • npm init -y: Create package.json with all default answers accepted.
  • npm set: Set defaults for when you run npm init.
  • npm get: Check a default setting used when running npm init.
  • npm config delete: Remove a default setting used when running npm init.
  • Settings are stored in the ~/.npmrc file in the root of the user directory.

 

Installing packages

  • npm install {package_name}: Install a package in your projects. Installs to the “node_modules” sub-directory of your current directory. Installs the latest version.
  • npm install {package_name} –save: Save it to the dependencies section of package.json file.
  • npm install {package_name} –save-dev: Save it to the ‘dev’ dependencies list of package.json file.
  • Install packages globally so they can be used across projects.
  • npm install {package_name} -g: Install a package globally to a special folder on your computer.
  • npm install {package_name}@{version_number}: Install a specific version of a package locally.
  • In package.json:
    {
      "dependencies": { "underscore": "^1.8.3" }
    }

    The “^” means if a new version of the package is published, the newest version will be installed (auto upgraded).
    It also means we only want the latest version of the major release (the first digit, in this example the minor version is 1).

  • In package.json:
    {
      "dependencies": { "underscore": "~1.8.3" }
    }

    The “~” means we only want the latest version of the minor release (the second digit, in this example the minor version is 1.8).

  • In package.json:
    {
      "dependencies": { "underscore": "*" }
    }

    The “*” means just wan the latest version of the library (regardless of major or minor release).

  • In package.json:
    {
      "dependencies": { "underscore": "1.8.3" }
    }

    Just the number means we even install that exact version of the library (in this example, 1.8.3).

  • npm install {package_name}@{version_number} –save –save-exact: Install a version of a package, and tell package.json to use the exact version (don’t auto upgrade) via the –save-exact flag.
  • After package.json is setup, a new use just needs to use npm install to install all package dependencies.
  • npm install {url}: Install a package from a specified URL (e.g. GitHub or hosted server).
  • npm install gist:{github_gist_hash}: Install a package from a GitHub gist. You can use –save with it.
    • After, if you use npm list you may see it marked with “npm ERR!  extraneous: ….”. That means “the package is installed but is not listed in your project’s package.json”.
    • If you save it to packages.json then list it out you may see it as “invalid”. You can ignore that. It has to do with not being in the npm registry.
  • To install a private/closed source package from a folder: npm install {path_to_package_folder}. (e.g. “npm install ../my-package”).
  • npm list: List of packages you’ve installed locally, with their dependent packages.
    • list will return a complete dependency tree, with all sub-sub-sub-etc dependencies.
    • You can return just the first level of packages by using npm list –depth=0. To include the first sub-level of package dependencies,
    • npm list –depth=1.
  • npm list –global or npm list -g: List of packages you’ve installed globally, with their dependent packages.
    • You can use –depth=x after -g same as with local packages.

 

Updating Packages

  • npm outdated: Checks the npm registry to see if any of the installed packages are outdated (i.e. newer versions are available).
  • npm update: npm will get the latest compatible version of your dependencies and updates them
    (Question: is this only looking at package.json? What if there is no package.json – does it just look at the installed modules? According to https://www.hostingadvice.com/how-to/update-npm-packages/: “The npm update command allows you to update any out-of-date packages, according to your package.json versions”. So my takeaway is that npm update requires package.json).
  • npm update –dev and npm update –prod: Update just development dependencies or production dependencies, respectively.
  • npm update {package_name}: Update a single dependency/package.
  • npm update -g: Update all global dependencies.
  • npm update -g {package_name}: Update a single package in global dependencies.

 

Removing Packages

  • npm uninstall {package_name}: Uninstall a package locally. Does not remove from the “dependencies in your package.json file.
  • npm uninstall {package_name} –save: Uninstall a package locally and remove from the “dependencies in your package.json file.
  • npm uninstall {package_name} -g: Uninstall a package from the global repository.
  • Pruning: Removing packages that are not listed in your package.json file (e.g. if you run npm list and notice an “extraneous” error in the results).
  • npm prune: Goes through and compares installed local packages to the package.json file and removes anything that should not be there.
  • npm prune {package_name}: Prune a single package. Essentially the same as npm remove.
  • npm prune –production: Removes all dev dependencies, which will leave your package (?? no, project) ready to go to production.

 

Running Scripts

  • Scripts: Create scripts that can be run in the “scripts” section of package.json
    • 2 default scripts: “test” and “start”.
    • npm test: Run the “test” script.
    • npm start: By convention, the script you will run to launch the project.
    • Example section in package.json:
      {
        "scripts": {
          "test": "node test.js",
          "start": "node index.js",
        }
      }
    • For other supported script names see https://docs.npmjs.com/misc/scripts.
    • You can also use your own custom script names (e.g. “uglify”: “gulp compress” to use gulp to compress and uglify the code. So you would run “npm run uglify”).
    • npm run {script}: Run a custom script.
    • The scripts section is good guidance for other developers on tasks to run in the project.

 

Other Actions

  • npm repo {package_name}: Take you to the official source repository for the package.
  • To upgrade NPM itself: npm install@latest -g. Note: must be run on a command-prompt with administrator privileges.
  • npm audit: (since npm v6) Run a security check on your dependencies (packages) for security issues.

 

Resources/tutorials

Notesheet: Git (Commands, Processes, and Tips)

Basic command-line commands to remember

git add * (or git add -u)

  • Add changed files in your workspace to staging, ready for commit.
  • -u if you find deleted files are not being added to the commit.

git commit -m “<you comments>”

  • Commit your staged files, giving a comment on what’s the changes/work relates to, ready for a push to origin.

git push

  • Push your staged files to the origin. The fill command would be “git command <origin> <branch>”

git fetch

  • Fetch the latest changes from the repository origin so you can then see if your local branch is ahead or behind the origin.

Check If ‘Origin’ Has Changes

To check if ‘origin’ (i.e. GitHub) has changes – on any branch – simply use git fetch.

This will fetch the latest history from the respository ‘origin’, and a git status on your branch will tell you if your branch is behind.

After that use git pull to pull down the actual changes to the branch.

Merge Changes From Another Branch

To merge changes from another branch into your own:

  1. Make sure the local copy of the branch you’re merging from (let’s use ‘develop’ in this example) is up to date locally. So: git pull.
  2. Change to the branch you want to merge ‘develop’ into.
  3. Run the merge command: git merge <branch> (where in this example <branch> is develop, so run git merge develop).

I usually do this with a Windows GUI client (Sourcetree or GitHub Desktop) client, but it should be the same for command-line:
at this point, if you had no merge conflicts then the merged changes should already be staged and committed (i.e. the same as doing a “git add” followed but “git commit”, ready for a “git push”).

If you get merge issues then git sometimes can’t figure out how to merge some code together. In this case, you need to resolve it by manually picking the correct code from each branch to make the final merged code.
I’ve never done this on the command-line (I use GUI tools like WinMerge or BeyondCompare which make comparing and selecting code much easier).


Always merge from ‘develop’ before a Pull Request

(This assumes we’re using the Git Flow process and ‘develop’ is our primary working branch.)

After you complete a piece of work and before you initiate a Pull Request to merge your changes to ‘develop’, first merge from ‘develop’ to your branch to ensure the 2 are synced up and to check for any conflicts.


Tips for Managing and Merging Branches

Merging can be dangerous at times when conflicts happen.

It may seem obvious, but I always use the following trick when merging another branch (like ‘develop’ from Git Flow) into mine:

  1. Stage and commit all my current work.
  2. Push all commits to origin.
  3. Then merge from the other branch.

If you don’t want to commit then replace steps 1 and 2 by making a “backup” stash of your active work before the merge.

This way, if there merge goes really wrong you can just reset your local branch (and un-stash your changes if you stashed to a backup) and start again.


Branch Tracking

See https://stackoverflow.com/questions/4693588/git-what-is-a-tracking-branch

If you lose the branch tracking against a remote branch or need to change the tracking, you can do it like the following example:

git branch –set-upstream-to=origin/feature/jason feature/jason

On the command-line, if Git automatically detects a lack of tracking it will show a message like this:

If you wish to set tracking information for this branch you can do so with:
git branch –set-upstream-to=origin/<branch> <local-branch>

Reset Changes to Your Local Branch

If you have uncommitted changes in your local branch, or you’ve merged from another branch you want to try again, you can reset file changes in your uncommitted workspace back to the last commit on the branch.
That is: You can delete any file modifications since the last successful commit of code you know is good on your branch.

Can use this command on your branch:

git reset –hard

Resolve Merge Conflicts ion the Command Line

I’ve never resolved merge conflicts at the command line (I use a Windows GUI tool), however, if you need help do a Google search on “git command line fix conflicts”.
The following 2 pages that should get you started:
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/
https://www.git-tower.com/learn/git/ebook/en/command-line/advanced-topics/merge-conflicts

Here’s an example of how to resolve a conflict using the code from your branch.

Open the file with conflicts in an editor and search for ‘<<<<<<<‘.
Your changes are between ‘<<<<<<<‘ and ‘=======’.
Delete the lines with ‘<<<<<<<‘, ‘ =======’ and ‘>>>>>>>’ and anything between ‘=======’ and ‘>>>>>>>’ (which is code from the branch you merged into your branch).
The following example helps illustrate this. Note the “HEAD” (your branch) and “develop” (the branch merged into your branch).

Example:

+ <<<<<<< HEAD
else
+ =======
+ else
+ >>>>>>> develop

Good Git Resources