Convert SVG to PNG with a single line of code

HTML element img accepts an SVG file as its source, therefore you can convert SVG to PNG with a single line of code:

<img src="svg-logo.svg" />

Then you can save it as a PNG image. This way is not only the simplest, but also gets the same picture quality as the SVG file.

You can also set a customized size for it:

<img src="svg-logo.svg" width="256" height="256" />


Note: If your SVG references a font, the font will be replaced by a default one in the image, meaning referenced fonts are not supported.

Other methods

Using HTML5 canvas

svg to png provides a more complicated method, it uses HTML5 canvas’s drawImage method to draw the SVG on canvas and gets an encoded PNG from it.

var svg     = document.querySelector('#svg'),
    img     = document.querySelector('#png'),
    canvas   = document.createElement('canvas'),   // New element
    context  = can.getContext('2d'),
    loader   = new Image;

loader.width  = canvas.width  = tgtImage.width;
loader.height = canvas.height = tgtImage.height;
loader.onload = function(){
  context.drawImage(loader, 0, 0, loader.width, loader.height);
  tgtImage.src = can.toDataURL();
var svgXML = (new XMLSerializer).serializeToString(svg);
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svgXML);

I found there will be a loss of picture quality obtained in this way. It also does not support referenced fonts.


svgexport is a open-source nodejs module. You need to install node.js and install svgexport module before using it.

The biggest issue is that it does not support referencing elements in SVG.

JavaScript Array Operations with Examples

JavaScript Array Operations with Examples

This article illustrates the operations of JavaScript Array. These examples include built-in APIs and some custom functions, such as groupBy, union, objectToArray, etc.

Note if fruits is not initialized in examples, it is:

let fruits = ['Apple', 'Banana'];

Basic operations


let fruits = ['Apple', 'Banana'];
let length = fruits.length;
// 2

let fruits1 = [];
fruits1.push('Apple'); // ['Apple']
fruits1.push('Banada');// ['Apple', 'Banana'];

let fruits2 = new Array('Apple', 'Banana');

// Creates an array of 2 empty slots, not slots with actual undefined values
let fruit3 = new Array(2); 
// Array [undefined, undefined]

Create an two-dimensional array

let board = [ 

Set values

Set values directly

fruits[1] = 'Blackberry';

If you set a value at a new indexed position which is not contained in the array. The length of the array will be updated accordingly.

let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits));  // ['0', '1', '4']

**Fill values **

The fill() method fills (modifies) all the elements of an array from a start index (default zero) to an end
index (default array length) with a static value. It returns the modified array.

Syntax: fill(value[, start[, end]])

let array1 = [1, 2, 3, 4];

// fill with 0 from position 2 until position 4
console.log(array1.fill(0, 2, 4));
// expected output: [1, 2, 0, 0]

// fill with 5 from position 1
console.log(array1.fill(5, 1));
// expected output: [1, 5, 5, 5]

// expected output: [6, 6, 6, 6]


Access an element through index

let first = fruits[0];
// Apple

let last = fruits[fruits.length - 1];
// Banana

Note: It is possible to quote the array indexes, such as fruits['0'], although it is not necessary. The 0 in fruits[0] is coerced into a string by the JavaScript engine through an implicit toString conversion.

Get index of an element

let index = fruits.indexOf('Banana');
// 1


Add to the end of an array

// push() changes the length and returns the new length
let newLength = fruits.push('Coconut'); // ["Apple", "Banana", "Coconut"]
// 3

Add to the front of an array

// unshift() changes the length and returns the new length
let newLength = fruits.unshift('Avocado');// ["Avocado", "Apple", "Banana"];
// 3

Add by setting a value at a new index position

let fruits = ['Apple', 'Banana'];
fruits[4] = 'Damson';
console.log(fruits); // ['Apple', 'Banana', undefined, undefined, 'Damson'];
console.log(furits.length); // 5
console.log(Object.keys(fruits));  // ['0', '1', '4']

When setting a property on a JavaScript array when the property is an valid array index and that index is outside the current bounds of the array, the engine will update the array’s length property accordingly.

Add a value at a specific position

The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.

let fruits = ['Apple', 'Banada', 'Coconut'];

// Remove 0 item from index of 1, and adding new item 'Blueberry'
let deletedItems = fruits.splice(1, 0, 'Blueberry'); // Add at index 
// deletedItems: []
// fruits: ['Apple', 'Blueberry', Banada', 'Coconut']


Remove from the end of an array

// pop() returns the removed element, it changes the length
// remove Banada from the end
let last = fruits.pop(); // ["Apple"];
// Banada

Remove from the front of an array

// shift() returns the removed element, it changes the length
// remove Apple from the front
let first = fruits.shift(); // ["Banana"];
// Apple


There are several ways to loop over an array. Use mapreducefilter functions first if they satisfy your needs, otherwise use below loop operations. Although these function are slower, they are easier to code、read , maintain and test. See for vs for each vs (map, reduce, filter, find) for details.

Use for loop

for (let i = 0; i < furits.length; ++i) {

Use forEach method

The forEach() method executes a provided callback function once for each array element.

// The parameters of index and array are optional
fruits.forEach(function(currenValue, index, array) {
  console.log(curentValue, index);
// "Apple" 0
// "Banada" 1

Note: It is not invoked for index properties that have been deleted or are uninitialized. For example:

const arraySparse = [1,3,,7];
let numCallbackRuns = 0;

console.log(arraySparse); // 3

Formatted print

Use console.table

console.table displays tabular data as a table. This feature is available in Web Workers.

console.table(['Apple', 'Banada']);
console.table(board); // prints a two-demensional array

Write your own function

function printArrayElements(element, index, array) {
  console.log('a[' + index + '] = ' + element);

// a[0] = "Apple"
// a[1] = "Banada"

Other Operations


Copy a new array

The slice(begin, end) method returns a shallow copy of a portion of an array into a new array object (end not included) . The original array will not be modified.

let fruits = ['Apple', 'Banada'];
let shallowCopy = fruits.slice(); // this is how to make a copy
// ["Apple", "Banada"]

Syntax: slice([begin[, end]]).

Copy elements to the same array

The copyWithin(target, start, end) method shallow copies part of an array to target location in the same array and returns it without modifying its length.

Syntax: copyWithin(target[, start[, end]]).

let array1 = ['a', 'b', 'c', 'd', 'e'];

// copy to index 0 the element at index 3
console.log(array1.copyWithin(0, 3, 4));
// expected output: Array ["d", "b", "c", "d", "e"]

// copy to index 1 all elements from index 3 to the end
console.log(array1.copyWithin(1, 3));
// expected output: Array ["d", "d", "e", "d", "e"]


The filter() method creates a new array with all elements that pass the test implemented by the provided function.

let fruits = ['Apple', 'Banana', 'Blueberry'];
let bfruits = fruits.filter(val => val.startsWith('B'));
// ['Banana', 'Blueberray']


Find the index

findIndex()method returns the index of the first element in the array that satisfies the provided testing function.

let furits = ['Apple', 'Banana'];

function startsWithB(element) {
  return element.startsWith('B');

// expected output: 1

Find the element

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

let array1 = [5, 12, 8, 130, 44];

let elemnent = array1.find(function(element) {
  return element > 10;

// 12

Check whether an array includes a certain value

The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.

Syntax: includes(valueToFind[, fromIndex])

let fruits = ['Apple', 'Banana'];
console.log(fruits.includes('Orange'));// false
console.log(fruits.includes('App'));// false

Note: When comparing strings and characters, includes() is case-sensitive.

Note: Technically speaking, includes() uses the sameValueZero algorithm to determine whether the given element is found.


The join(sperator) method creates and returns a new string by concatenating all of the elements in an array (or an array-like object), separated by commas or a specified separator string

let fruits = ['Apple', 'Banada'];

// expected output: "Apple,Banada"

// expected output: "Apple-Banada"

Merge / Concat

The concat()method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

let array1 = ['a', 'b', 'c'];
let array2 = ['d', 'e', 'f'];

// Array ["a", "b", "c", "d", "e", "f"]



The reverse() method reverses an array in place. The first array element becomes the last, and the last array element becomes the first.

let array1 = ['one', 'two', 'three'];
let reversed = array1.reverse();
console.log(array1); // Array ['three', 'two', 'one']
console.log(reversed); // Array ['three', 'two', 'one']


Every: Test whether all elements pass provided function

The every() method tests whether all elements in the array pass the test implemented by the provided function.

function isBelowThreshold(currentValue) {
  return currentValue < 40;

let array1 = [1, 30, 39, 29, 10, 13];
// true

Note: This method returns true for any condition put on an empty array.

Some: Test whether at least some elements pass provided function

The some() method tests whether at least one element in the array passes the test implemented by the provided function.

let even = function(element) {
  // checks whether an element is even
  return element % 2 === 0;

let array = [1, 2, 3, 4, 5];
// true

Note: This method returns false for any condition put on an empty array.


The Array.isArray() method determines whether the passed value is an Array.

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

isArray vs instance of

When checking for Array instance, Array.isArray is preferred over instanceof because it works through iframes.

String to Array, Map to Array, Set to Array

// ['f', 'o', 'o']

The Array.from() method creates a new, shallow-copied Array instance from an array-like or iterable object.

Array.from() lets you create Arrays from:

  • array-like objects (objects with a length property and indexed elements) or
  • iterable objects (objects where you can get its elements, such as Map and Set)
const set = new Set(['foo', 'bar', 'baz', 'foo']);
// ['foo', 'bar', 'baz']

Other loops: map vs reduce


map() method creates a new array with the results of calling a provided function on every element in the calling array.


let new_array = callback(currentValue[, index[, array]]) {
    // Return element for new_array
}[, thisArg]
  • currentValue, the current value in the array
  • index
  • array, the array itself
  • thisArg, Value to use as this when executing callback.


[1, 4, 9].map((val) => {
  return val * 2;
// It creates a new array: [2, 8, 18]


The reduce() method executes a callback on each element of the array, resulting in a single output value.


arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
  • accumulator

    The accumulator accumulates the callback’s return values. It is the accumulated value previously returned in the last invocation of the callback, or initialValue.

  • currentValue, the current element being processed in the array.

  • index, the index of the current element being processed in the array.

  • array, the array reduce() was called upon.

  • initialValue

    A value to use as the first argument to the first call of the callback. If no initialValue is supplied, the first element in the array will be used and skipped. Calling reduce() on an empty array without an initialValue will throw a TypeError.


// Get sum of an array
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
  return accumulator + currentValue;

Custom operations

Filter an Objects Array by fields

filter is an object which defines the filter condition. If an object in the array has the properties with the same values in filter, it will be filtered out.

const filterArray = (arr, filter) => {
  var data = [];
  for (let obj of arr) {
    let filtered = true;
    for (let p in filter) { // for each property in filter
      if (obj[p] != filter[p]) {
        filtered = false;

    if (filtered) {
  } // for

  return data;


let employees = [
  {name: 'Jane', gender: 'Female'},
  {name: 'Jim', gender: 'Male' },
  {name: 'Lily', gender: 'Female'}
filterArray(employees, {gender: 'Female'});
// [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}]


The following groupBy groups objects in an array by a field.

const groupBy = (arr, field) => {
  return arr.reduce(function (acc, obj) {
    let key = obj[field];
    acc[key] = acc[key] || [];
    return acc;
  }, {});


let employees = [
  {name: 'Jane', gender: 'Female'},
  {name: 'Jim', gender: 'Male' },
  {name: 'Lily', gender: 'Female'}
groupBy(employees, 'gender');
// { 
//   'Female': [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
//   'Male': [{name: 'Jim', gender: 'Male' }]
// }

If you want an array of grouped objects:

const groupBy = (arr, field) => {
  let groups = arr.reduce((acc, obj) => {
    let key = obj[field];
    acc[key] = acc[key] || [];
    return acc;
  }, {});

  return Object.keys(groups).map( group => {
    return groups[group];

The result will be:

// [
//   [{name: 'Jane', gender: 'Female'}, {name: 'Lily', gender: 'Female'}],
//   [{name: 'Jim', gender: 'Male' }]
// ]

A more generic version

Below code (from javascript codesnipt) is a more generic version. It accepts an array of basic types or objects. It has 2 processes:

  1. Use map to generate a new array. Here arr is the array, and f can be a function or a field name by which it is grouped.
  2. Use reduce function to produce a object in which a field indicates a group.
const groupBy = (arr, f) => f === 'function' ? f : val => val[f]).reduce((acc, val, i) => {
    acc[val] = (acc[val] || []).concat(arr[i]);
    return acc;
  }, {});


groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]}
groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}

Of course it can be completed in one loop:

const groupBy = (arr, f) => {
  return arr.reduce((acc, val) => {
    let key = (typeof f === 'function') ? f(val) : val[f]).
    acc[key] = acc[key] || [];
    return acc;
  }, {});


Union operation returns each item in any of a and b once.

const union = (a, b) => Array.from(new Set([...a, ...b]));


union([1, 2, 3], [4, 3, 2]); 
// [1,2,3,4]

The union above works only for primitive types. You can provides a comparison function to union other types.

const unionWith = (a, b, comp) =>
  Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));

It filters the elements that does not appear in a from b, then makes a merge operation.

Array to Set

let set = new Set(['Apple', 'Banana', 'Apple']);
// ('Apple', 'Banana')

Unique Values in Array

const uniqueValues(arr) => [ Set(arr)];

Object to Array

This operation convert an object to an array.

let objectToArray = obj => {
  Object.keys(obj).map(val => {
    return obj[val];


  • JavaScript Array.
  • JavaScript code snippet.

Submodules management in Git

Git’s submodule tool allows you to create a child repository as a submodule inside a repository. This article shows you how to manipulate a submodule.

Add a submodule from a remote repository

To create a new sub repository whose content does not exist in the repository:

# Add a submodule named a-submodule from an remote repository
# This command will create a .gitmodules which contains the mapping relation of
# the submodule and its remote repository.
# It also stages the changes.
$ git submodule add

# Use status to check what the above command stages
$ git status
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   .gitmodules
        new file:   a-submodule

# You need to commit staged changes: .gitmodules and a-submodule
$ git commit -m 'add a submodule'
[master 9d7d3b3] add: add a submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 a-submodule

As you see, Git treats the new submodule as a file with special mode (1600000) in a commit.

For a repository with submodules inside it, it is called the main repository.

Note: In new git versions, the submodule’ s .git data is stored the main repository’s .git directory while they stay in the submodule’s directory in the old versions.

Add a submodule from an subdirectory

You can also switch a subdirectory to a submodule. To add a submodule from an subdirectory which has been tracked, you need to remove it first:

# First remove the subdirectory named csvlib from index
$ git rm --cached csvlib

Then add a subdirectory as a submodule:

# Init csvlib as a repo
$ cd csvlib
$ git init
$ git add .
$ git commit -m 'initial commit'

# Add csvlib repo as a submodule
$ git submodule add ./csvlib/
Adding existing repo at 'csvlib' to the index

# Check status
$ git status
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   .gitmodules
        new file:   csvlib
        deleted:    csvlib/

# Commit the changes
$ git commit -m 'switch subdirectory csvlib as a submodule'
[master 9d7d3b3] add: add submodule git-submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 a-submodule

Note: If you switch to a branch which the subdirectory not being as a submodule,you may get an error for the subdirectory will be overwritten. At this time, an option -f is needed to checkout. Afterwards if you get back to the branch treating it as a submodule, you need to execute git checkout . in the submodule’s directory to get the content back. See more on git submodules.

Commit changes for a submodule

To commit changes in a submodule, first commit in its own repository and then commit for the main repository:

# Commit changes in the submodule directory
$ git add 
$ git commit -m 'feat: add some functionly'
# Push changes to its remote repository
$ git push

# Switch to the main repository directory
$ cd ..
# Check changes from a submodule
$ git status
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)

        modified:   a-submodule (modified content)

# Commit the submodule's changes to the top repository
$ git add a-submodule
$ git commit -m 'update changes of submodule a-submodule'
# Push changes if you want
$ git push

Pull updates for a submodule

To pull updates from remote for a submodule, an easy way is to run:

# Let Git to go into the submodule's directory and get updates for a-submodule
# --merge, merge local work
$ git submodule update --remote --merge a-submodule

Or you can do it manually:

# Switch to the submodule's directory
$ cd a-submodule

# Pull and merge updates form upstream branch
$ git pull
$ git merge origin/master

Manipulate multiple submodules at a time

Git has a submodule foreach command for you to manipulate multiple submodules. For example, stashing changes for all your submodules:

# Stash changes for all submodules
$ git submodule foreach 'git stash'

Remove a submodule from a repository

To remove a submodule named a-submodule from a repository:

# Frist remove the from index
$ git rm --cached a-submodule

# If you want to keep submodule's files in working tree.
# Rename it for the next command will delete it from working tree
$ mv a-submodule a-submodule-renamed

# Unregister the submodule
# This command removes it both from .git/config and working tree
$ git submodule deinit a-submodule

Adding categories navigation to WordPress header

To show categories in the header part of your website, create a new division in the header where you want them to display.

Before you start, you’d better create a child theme to make customization instead of directly modifying a theme. Take the default “twentyseventeen” theme for example, add below code to file templates-parts/header/site-branding.php of the theme:

       <div id="category-list">
                <li><a title="Home Page" href="index.php">home</a></li>
                <?php wp_list_categories(array('title_li' => '', 'echo' => 1)); ?>
        </div><!-- .category-list -->

wp_list_categories is used to display the categories list. You can use many parameters to control its result, below are some of them:

  • title_li, text for the list title <li> element

  • echo, display markup marks.

  • separator, separator between links.
  • exclude, array of strings to exclude.

Add below code in style.css to style the categories:

/* category list in header */
#category-list {
    margin: 0;
    display: inline-block;
    float: right;
    vertical-align: middle;
    font-size: 14px;
    font-style: normal;
    text-transform: capitalize;
#category-list li {
    display: inline; 
    list-style-type: none; 
    padding: 0px 5px;
#category-list a:link, #category-list a:visited {
    color: #eee;
#category-list a:hover {
    opacity: 0.7;

The display and list-style-type make the list a horizontal layout.

Here is the header with categories:

categories in header

Listing changed files in a commit

Use below command to list the changed files in a commit:

# List changed files in the specified commit
$ git show --name-only <commit>

# Examples

# List changed files in HEAD
$ git show --name-only HEAD
commit ea34837d870e48106ae9ad09f41297a64ad6a6a1 (HEAD -> master)
Author: xxx <>
Date:   Wed Mar 13 20:27:46 2019 +0800

    feat: add localization


If you only want the file names, use:

# List only names of changed files in HEAD
$ git diff --name-only HEAD~ HEAD

Exporting data to csv in WordPress with PHP

In WordPress plugin development, sometimes you may need to export data to a csv file. Here we share how to implement it with PHP code.

How to export a csv file with PHP code

header() is used to send a raw HTTP header. To export a generated csv file, use below headers to tell the browser display a save dialog.

header( 'Content-Type: text/csv' ); // Supply the mime type
header( 'Content-Disposition: attachment; filename="downloaded.pdf"' ); // Supply a file name to save


There is not official RFC document for CSV files. text/csv is not a standard mime type, but it is more clear and works fine. application/octet-stream can also be used for csv files. However it is a very generous and it does not hint which application should be used to open the file.

Use two more headers to tell the content should not be cached by browser or any caches between the server and the browser.

header( "Cache-Control: no-cache, must-revalidate" );
header( "Expires: Sat, 26 Jul 1997 05:00:00 GMT" ); // Date in the past

Then echo the generated csv content directly:

echo $csv;


Any actual content must be output after header(). One common error is outputting content before header() by include or require a file. See more about header().

Below is the full example.

Example: Export data to csv in WordPress

Add an export button:

<a href="admin.php?page=export_example&export=table&noheader=1">Export</a>

Don’t forget add the argument named “noheader”. Otherwise, the csv content will directly be printed and there will be no Save dialog box popping up in the browser.

Process the export in the same file:

$table_head = array( 'column1', 'column2', 'column3' );
$table_body = array(
    array( 'a', 'b', 'c' ),
    array( 'd', 'e', 'f' )

// Process export
if( isset( $_GET['export'] ) ) {
    $csv = implode( $table_head, ',' );
    $csv .= "n"; // important! Make sure to use use double quotation marks.
    foreach( table_body as row ) {
        $csv .= implode( $row, ',' );
        $csv .= "n";

    $filename = 'table.csv';    
    header( 'Content-Type: text/csv' ); // tells browser to download
    header( 'Content-Disposition: attachment; filename="' . $filename .'"' );
    header( 'Pragma: no-cache' ); // no cache
    header( "Expires: Sat, 26 Jul 1997 05:00:00 GMT" ); // expire date

    echo $csv;
<a href="admin.php?page=export_example&export=table&noheader=1">Export</a>

This example works well on Firefox, IE, Chrome.

Export data with Unicode characters to utf-8 bom csv

If your data contains Unicode characters, you may want to export a utf-8 bom csv that Excel will read properly. To achieve that, just output the BOM mark before data:

echo "xEFxBBxBF"; // UTF-8 BOM
echo $csv;

Fixing JetPack related posts not showing for XMLRPC parse error

JetPack related posts are not showing, WordPress says This site cannot be accessed, and xmlrpc test shows parse error. not well formed . Here it shows you how to fix it.

Test your site

Run below command to test your site in an terminal (Any computer is fine.)

$ curl -A "Jetpack by" -d "<methodCall><methodName>demo.sayHello</methodName></methodCall>" https://www.your

The correct result should be:

<?xml version="1.0" encoding="UTF-8"?>

It is a XMLRPC parse error if the response is:

<?xml version="1.0" encoding="UTF-8"?>
          <value><string>parse error. not well formed</string></value>

Tips: You can also test your site using Just input your site and click Check button. Other information like username and password is not needed.

If it is an XMLRPC parse error, the result will be:

Code      Description
-32700    parse error. not well formed

Solution for parse error

Connect to your website host, run below command to install php-xml:

$ sudo apt-get install php-xml

If your host does not have apt-get installed, you may need use (Such as AWS EC2 with Amazon Linux 2):

$ sudo yum install php-xml

Retest your site, it should be OK (Restart your apache sever if needed). After your posts are synced to WordPress site, you may see related posts.

Note: Related posts will not appear unless at least 3 good related posts can be found by JetPack. See more on jetpack related posts.

Tips: For other JectPack connection issues,fix them according to fixing jetpack connection issues.




  • Partial clone

    How to clone only part of commits of a huge repository



  • Stash changes

    How to save changes temporally, apply changes, list stashes, delete a stash?




  • Remote management

    How to add a remote, delete a remote, change the URL of a remote, etc.


  • Differences

    How to check differences between working tree, index, a specific commit?




  • Check log

    How to view the last several commits, search the commit history with string, list the commits graphically, check which commit changed a string, etc.

Deleting files from Git commit history

If you commits an sensitive file or a huge unwanted file, you may want to remove it from every commit. Git provides a nuclear-level command git filter-branch which allows you rewrite the history.

git filter-branch executes the specified command for each commit specified by you and generates new commits.

Before you start, you must keep it in mind that this operation changes the existing history. If it is a public repository and someone have did some work based on the commits you want to rewrite, you’d better not do this. If you have to, remember to notify them to run git pull --rebase command.

Delete a huge folder from every commit

Here is an example of how to remove a huge folder from each commit which is committed accidentally at first.

You’d better test below commands in a temporary repository to make sure that they work properly for your git version. It is met that git filter-branch below removes the folder in working tree as well but it should not.

We do it in a new testing branch, when the result is what we want then reset it as the prior branch.

# Do it in a new testing branch
$ git checkout -b test

# Remove 'build' folder from every commit on the new branch
# --index-filter, rewrite index without checking out
# -r, remove recursively in subfolders
# --cached, remove it from index but not include working tree
# --ignore-unmatch, ignore if files to be removed are absent in a commit
# --prune-empty, remove empty commits generated by 'git rm' command
# HEAD, execute the specified command for each commit reached from HEAD by parent link
$ git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch build' --prune-empty HEAD
Rewrite fee4b8ee9df321a877cd2663b20b293eea4a1f8c (1/2)rm 'build/'
Rewrite 63f272ab5152c66693614efae77567799837c6e0 (2/2)
Ref 'refs/heads/test-filter' was rewritten

# The output is OK, reset it to the prior branch master
$ git checkout master
$ git reset --soft test

# Remove test branch
$ git branch -rm test

# Push it with force
$ git push --force origin master

If you changed commits in remote repository, remember notice other members execute below command:

# Tell others to execute below command if you changed commits in remote repository.
$ git pull --rebase


  1. If --ignore-unmatch option is not added, it will fail when the files to be removed do not exist in a commit.
  2. The files you removed will stay in disk for a while, they will be removed entirely in the next automic garbage collection of git.

Tips: To avoid adding unwanted files accidently, you should ignore it.

Other useful options:

# Execute the specified command for the last 5 commit
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch user.pem' HEAD~6..HEAD

# Execute the specified command for all branches
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch user.pem' -- --all

# Update tags when executing filter-branch, remember to push them to remotes afterwards
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch user.pem' --tag-name-filter cat HEAD

# Remove empty commits generated by 'git rm' command
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch user.pem' --prune-empty HEAD

Remotes management in Git

In Git, you can have more than one remote repository. git remote command is used to manage them. Operations illustrated include how to add a remote, remove a remote, view a remote’s information, change a remote’s URL, etc.

Add a remote

# Add a remote
$ git remote add <name> <url>

# Examples:
# Add a remote named test
$ git rmeote add test

Note: When you clone a remote repository, Git sets the remote as origin for you automatically.

List remotes

# Show remotes with names
$ git remote

# Show remotes with names, urls
$ git remote -v
origin (fetch)
origin (push)

Change URL of a remote

# Chang url of origin
$ git remote set-url origin

Verify its URL has changed:

$ git remote get-url origin

Get URL of a remote

# Get the url of origin
$ git remote get-url origin

Fetch updates from a remote

# Fetch updates from the remote named origin
$ git remote update origin

Rename a remote

# Rename a remote
$ git remote rename <old> <new>

# Examples:
# Rename origin to main
$ git remote rename origin main

Remove a remote

# Remove a remote
# Note: all the remote-tracking branches and settings 
# for the remote are removed.
$ git remote remove <name>

# Examples:
# Remove the remote nameed server2
$ git remote remove server2