Index: src/wp-includes/category-template.php
===================================================================
--- src/wp-includes/category-template.php	(revision 30351)
+++ src/wp-includes/category-template.php	(working copy)
@@ -402,6 +402,14 @@
 			$output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$selected>$show_option_none</option>\n";
 		}
 
+		if ( $r['selected'] ) {
+			// Check if the 'selected' term was split
+			$selected_term = get_term( $r['selected'], $r['taxonomy'] );
+			if ( $selected_term && ! is_wp_error( $selected_term ) && intval( $r['selected'] ) != $selected_term->term_id ) {
+				$r['selected'] = $selected_term->term_id;
+			}
+		}
+
 		if ( $r['hierarchical'] ) {
 			$depth = $r['depth'];  // Walk the full depth.
 		} else {
Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 30351)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -306,4 +306,7 @@
 add_filter( 'determine_current_user', 'wp_validate_auth_cookie'          );
 add_filter( 'determine_current_user', 'wp_validate_logged_in_cookie', 20 );
 
+// Split term updates
+add_filter( 'split_shared_term', '_wp_check_split_default_terms', 10, 4 );
+
 unset($filter, $action);
Index: src/wp-includes/taxonomy.php
===================================================================
--- src/wp-includes/taxonomy.php	(revision 30351)
+++ src/wp-includes/taxonomy.php	(working copy)
@@ -1233,7 +1233,17 @@
 				" );
 				break;
 			default:
-				$terms = implode( ',', array_map( 'intval', $query['terms'] ) );
+				$terms = $query['terms'];
+
+				// If any passed term_ids were previously split, substitute the correct term_id.
+				foreach ( $terms as $term_index => $term_id ) {
+					if ( $split_term = _get_split_term( $term_id, $query['taxonomy'] ) ) {
+						$terms[ $term_index ] = $split_term;
+					}
+				}
+
+				$terms = implode( ',', array_map( 'intval', $terms ) );
+
 				$terms = $wpdb->get_col( "
 					SELECT $resulting_field
 					FROM $wpdb->term_taxonomy
@@ -1315,6 +1325,12 @@
 			return null;
 		if ( ! $_term = wp_cache_get( $term, $taxonomy . ':terms:' . $incrementor ) ) {
 			$_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND t.term_id = %d LIMIT 1", $taxonomy, $term) );
+
+			// If no term is found, check whether this was a previously split term.
+			if ( ! $_term && $old_term_id = _get_split_term( $term, $taxonomy ) ) {
+				return get_term( $old_term_id, $taxonomy, $output, $filter );
+			}
+
 			if ( ! $_term )
 				return null;
 			wp_cache_add( $term, $_term, $taxonomy . ':terms:' . $incrementor );
@@ -1675,6 +1691,35 @@
 	 */
 	$args = apply_filters( 'get_terms_args', $args, $taxonomies );
 
+	/*
+	 * For parameters that accept term_ids, check to see whether any of the IDs passed to the parameter correspond
+	 * to previously split taxonomy terms. If so, swap out the old term_id for the new one, so the query matches.
+	 */
+	$term_id_params = array( 'exclude', 'exclude_tree', 'include', 'parent', 'child_of' );
+	foreach ( $term_id_params as $term_id_param ) {
+		if ( empty( $args[ $term_id_param ] ) ) {
+			continue;
+		}
+
+		$param_is_array = is_array( $args[ $term_id_param ] );
+
+		$passed_term_ids = (array) $args[ $term_id_param ];
+		foreach ( $passed_term_ids as $passed_term_index => $passed_term_id ) {
+			foreach ( $taxonomies as $taxonomy ) {
+				if ( $split_term = _get_split_term( $passed_term_id, $taxonomy ) ) {
+					$passed_term_ids[ $passed_term_index ] = $split_term;
+					continue 2;
+				}
+			}
+		}
+
+		if ( $param_is_array ) {
+			$args[ $term_id_param ] = $passed_term_ids;
+		} else {
+			$args[ $term_id_param ] = $passed_term_ids[0];
+		}
+	}
+
 	$child_of = $args['child_of'];
 	if ( $child_of ) {
 		$hierarchy = _get_term_hierarchy( reset( $taxonomies ) );
@@ -3903,6 +3948,24 @@
 }
 
 /**
+ * Look up a previously split taxonomy term by its old term_id.
+ *
+ * Terms that have been split by _split_shared_term() are stored, so that
+ * attempts to retrieve terms by the previous term_id still work.
+ *
+ * @since 4.1.0
+ * @access private
+ *
+ * @param int    $old_term_id Old, pre-split term_id.
+ * @param string $taxonomy    Taxonomy name.
+ */
+function _get_split_term( $old_term_id, $taxonomy ) {
+	$split_terms = get_option( '_split_terms_' . $taxonomy );
+
+	return ! empty( $split_terms[ $old_term_id ] ) ? $split_terms[ $old_term_id ] : null;
+}
+
+/**
  * Add count of children to parent count.
  *
  * Recalculates term counts by including items from child terms. Assumes all
@@ -4115,21 +4178,53 @@
 		clean_term_cache( $term_id, $shared_term_taxonomy );
 	}
 
+	// Keep a record of term_ids that have been split, keyed by old term_id.
+	$split_term_data = get_option( '_split_terms_' . $term_taxonomy->taxonomy, array() );
+	$split_term_data[ $term_id ] = $new_term_id;
+	if ( false === get_option( '_split_terms_' . $term_taxonomy->taxonomy, false ) ) {
+		add_option( '_split_terms_' . $term_taxonomy->taxonomy, $split_term_data, '', 'no' );
+	} else {
+		update_option( '_split_terms_' . $term_taxonomy->taxonomy, $split_term_data );
+	}
+
 	/**
 	 * Fires after a previously shared taxonomy term is split into two separate terms.
 	 *
 	 * @since 4.1.0
 	 *
-	 * @param int $term_id          ID of the formerly shared term.
-	 * @param int $new_term_id      ID of the new term created for the $term_taxonomy_id.
-	 * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
+	 * @param int    $term_id          ID of the formerly shared term.
+	 * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
+	 * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
+	 * @param string $taxonomy         Taxonomy for the split term.
 	 */
-	do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id );
+	do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id, $term_taxonomy->taxonomy );
 
 	return $new_term_id;
 }
 
 /**
+ * Check default categories when a term gets split to see if any of them need
+ * to be updated.
+ *
+ * @since 4.1.0
+ * @access private
+ *
+ * @param int    $term_id          ID of the formerly shared term.
+ * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
+ * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
+ * @param string $taxonomy         Taxonomy for the split term.
+ */
+function _wp_check_split_default_terms( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
+	if ( 'category' == $taxonomy ) {
+		foreach ( array( 'default_category', 'default_link_category', 'default_email_category' ) as $option ) {
+			if ( $term_id == get_option( $option, -1 ) ) {
+				update_option( $option, $new_term_id );
+			}
+		}
+	}
+}
+
+/**
  * Generate a permalink for a taxonomy term archive.
  *
  * @since 2.5.0
Index: tests/phpunit/tests/term/splitSharedTerm.php
===================================================================
--- tests/phpunit/tests/term/splitSharedTerm.php	(revision 30351)
+++ tests/phpunit/tests/term/splitSharedTerm.php	(working copy)
@@ -4,7 +4,7 @@
  * @group taxonomy
  */
 class Tests_Term_SplitSharedTerm extends WP_UnitTestCase {
-	protected $tt_ids = array();
+	protected $terms = array();
 
 	public function setUp() {
 		global $wpdb;
@@ -40,11 +40,11 @@
 			'parent' => $t1['term_id'],
 		) );
 
-		$this->tt_ids = array(
-			't1' => $t1['term_taxonomy_id'],
-			't2' => $t2['term_taxonomy_id'],
-			't3' => $t3['term_taxonomy_id'],
-			't2_child' => $t2_child['term_taxonomy_id'],
+		$this->terms = array(
+			't1' => $t1,
+			't2' => $t2,
+			't3' => $t3,
+			't2_child' => $t2_child,
 		);
 
 		_split_shared_term( $t1['term_id'], $t2['term_taxonomy_id'] );
@@ -55,9 +55,9 @@
 	 * @ticket 5809
 	 */
 	public function test_should_create_new_term_ids() {
-		$t1_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t1'], 'wptests_tax' );
-		$t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
-		$t3_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t3'], 'wptests_tax_3' );
+		$t1_term = get_term_by( 'term_taxonomy_id', $this->terms['t1']['term_taxonomy_id'], 'wptests_tax' );
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+		$t3_term = get_term_by( 'term_taxonomy_id', $this->terms['t3']['term_taxonomy_id'], 'wptests_tax_3' );
 
 		$this->assertNotEquals( $t1_term->term_id, $t2_term->term_id );
 		$this->assertNotEquals( $t1_term->term_id, $t3_term->term_id );
@@ -68,26 +68,26 @@
 	 * @ticket 5809
 	 */
 	public function test_should_retain_child_terms_when_using_get_terms_parent() {
-		$t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
 		$children = get_terms( 'wptests_tax_2', array(
 			'parent' => $t2_term->term_id,
 			'hide_empty' => false,
 		) );
 
-		$this->assertEquals( $this->tt_ids['t2_child'], $children[0]->term_taxonomy_id );
+		$this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
 	}
 
 	/**
 	 * @ticket 5809
 	 */
 	public function test_should_retain_child_terms_when_using_get_terms_child_of() {
-		$t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
 		$children = get_terms( 'wptests_tax_2', array(
 			'child_of' => $t2_term->term_id,
 			'hide_empty' => false,
 		) );
 
-		$this->assertEquals( $this->tt_ids['t2_child'], $children[0]->term_taxonomy_id );
+		$this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
 	}
 
 	/**
@@ -121,4 +121,108 @@
 		$t2_children = get_term_children( $t2['term_id'], 'wptests_tax_4' );
 		$this->assertEquals( array( $new_term_id ), $t2_children );
 	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_get_term_by() {
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+
+		$this->assertEquals( $t2_term, get_term_by( 'id', $this->terms['t1']['term_id'], 'wptests_tax_2' ) );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_get_term() {
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+
+		$this->assertEquals( $t2_term, get_term( intval( $this->terms['t1']['term_id'] ), 'wptests_tax_2' ) );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_get_terms_with_parent_param() {
+		$found = get_terms( 'wptests_tax_2', array(
+			'parent' => $this->terms['t1']['term_id'],
+			'hide_empty' => false,
+		) );
+		$this->assertEquals( $this->terms['t2_child']['term_id'], $found[0]->term_id );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_get_terms_with_include_param() {
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+
+		$found = get_terms( 'wptests_tax_2', array(
+			'include' => array( $this->terms['t1']['term_id'] ),
+			'hide_empty' => false,
+		) );
+		$this->assertEquals( $t2_term->term_id, $found[0]->term_id );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_tax_query() {
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+
+		$tq = new WP_Tax_Query( array(
+			array(
+				'field' => 'term_id',
+				'taxonomy' => 'wptests_tax_2',
+				'terms' => array( $this->terms['t1']['term_id'] ),
+			),
+		) );
+		$tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
+
+		$this->assertEquals( array( $t2_term->term_taxonomy_id ), $tq->queries[0]['terms'] );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_remain_available_at_old_term_id_using_wp_dropdown_categories() {
+		$t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
+		$terms = get_terms( 'wptests_tax_2', array( 'hide_empty' => false ) );
+		$dropdown = wp_dropdown_categories( array(
+			'echo'       => false,
+			'taxonomy'   => 'wptests_tax_2',
+			'hide_empty' => false,
+			'selected'   => $this->terms['t1']['term_id'],
+		) );
+
+		$this->assertRegExp( "/<option[^>]+value=\"{$t2_term->term_id}\" selected=\"selected\">/", $dropdown );
+	}
+
+	/**
+	 * @ticket 30335
+	 */
+	public function test_should_update_default_category_on_term_split() {
+		global $wpdb;
+		$t1 = wp_insert_term( 'Foo Default', 'category' );
+
+		update_option( 'default_category', $t1['term_id'] );
+
+		register_taxonomy( 'wptests_tax_5', 'post' );
+		$t2 = wp_insert_term( 'Foo Default', 'wptests_tax_5' );
+
+		// Manually modify because split terms shouldn't naturally occur.
+		$wpdb->update( $wpdb->term_taxonomy,
+			array( 'term_id' => $t1['term_id'] ),
+			array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
+			array( '%d' ),
+			array( '%d' )
+		);
+
+		$this->assertEquals( $t1['term_id'], get_option( 'default_category', -1 ) );
+
+		$new_term_id = _split_shared_term( $t1['term_id'], $t1['term_taxonomy_id'] );
+
+		$this->assertNotEquals( $new_term_id, $t1['term_id'] );
+		$this->assertEquals( $new_term_id, get_option( 'default_category', -1 ) );
+	}
 }
