diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
index f06ceeef19ac6743527a963603a4c5f418932bd2..9d168aa0b29391cf093bf4c4c152bf6de5e2be0a 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties-MERGED
@@ -394,6 +394,7 @@ OsAccountStatus.Unknown.text=Unknown
 OsAccountStatus.Active.text=Active
 OsAccountStatus.Disabled.text=Disabled
 OsAccountStatus.Deleted.text=Deleted
+OsAccountStatus.NonExistent.text=Non Existent
 OsAccountType.Unknown.text=Unknown
 OsAccountType.Service.text=Service
 OsAccountType.Interactive.text=Interactive
diff --git a/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java b/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java
index 2ad57d7023bceb23177617ac178ae16e622e7547..19d10064b854566cccba009646acff3a92368ddf 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/OsAccountManager.java
@@ -864,37 +864,11 @@ void mergeOsAccountsForRealms(OsAccountRealm sourceRealm, OsAccountRealm destRea
 			}
 
 			// Look for matching destination account
-			OsAccount matchingDestAccount = null;
-
-			// First look for matching unique id
-			if (sourceAccount.getAddr().isPresent()) {
-				List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
-						.filter(p -> p.getAddr().equals(sourceAccount.getAddr()))
-						.collect(Collectors.toList());
-				if (!matchingDestAccounts.isEmpty()) {
-					matchingDestAccount = matchingDestAccounts.get(0);
-				}
-			}
-
-			// If a match wasn't found yet, look for a matching login name.
-			// We will merge only if:
-			// - We didn't already find a unique ID match
-			// - The source account has no unique ID OR the destination account has no unique ID
-			// - destination account has a login name and matches the source account login name
-			if (matchingDestAccount == null && sourceAccount.getLoginName().isPresent()) {
-				List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
-						.filter(p -> p.getLoginName().isPresent())
-						.filter(p -> (p.getLoginName().get().equalsIgnoreCase(sourceAccount.getLoginName().get())
-						&& ((!sourceAccount.getAddr().isPresent()) || (!p.getAddr().isPresent()))))
-						.collect(Collectors.toList());
-				if (!matchingDestAccounts.isEmpty()) {
-					matchingDestAccount = matchingDestAccounts.get(0);
-				}
-			}
+			Optional<OsAccount> matchingDestAccount = getMatchingAccountForMerge(sourceAccount, destinationAccounts);
 
 			// If we found a match, merge the accounts. Otherwise simply update the realm id
-			if (matchingDestAccount != null) {
-				mergeOsAccounts(sourceAccount, matchingDestAccount, trans);
+			if (matchingDestAccount.isPresent()) {
+				mergeOsAccounts(sourceAccount, matchingDestAccount.get(), trans);
 			} else {
 				String query = "UPDATE tsk_os_accounts SET realm_id = " + destRealm.getRealmId() + " WHERE os_account_obj_id = " + sourceAccount.getId();
 				try (Statement s = trans.getConnection().createStatement()) {
@@ -906,6 +880,70 @@ void mergeOsAccountsForRealms(OsAccountRealm sourceRealm, OsAccountRealm destRea
 			}
 		}
 	}
+	
+	/**
+	 * Checks for matching account in a list of accounts for merging
+	 * @param sourceAccount The account to find matches for
+	 * @param destinationAccounts List of accounts to match against
+	 * @return Optional with OsAccount, Optional.empty if no matching OsAccount is found.
+	 */
+	private Optional<OsAccount> getMatchingAccountForMerge(OsAccount sourceAccount, List<OsAccount> destinationAccounts) {
+		// Look for matching destination account
+		OsAccount matchingDestAccount = null;
+
+		// First look for matching unique id
+		if (sourceAccount.getAddr().isPresent()) {
+			List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
+					.filter(p -> p.getAddr().equals(sourceAccount.getAddr()))
+					.collect(Collectors.toList());
+			if (!matchingDestAccounts.isEmpty()) {
+				matchingDestAccount = matchingDestAccounts.get(0);
+			}
+		}
+
+		// If a match wasn't found yet, look for a matching login name.
+		// We will merge only if:
+		// - We didn't already find a unique ID match
+		// - The source account has no unique ID OR the destination account has no unique ID
+		// - destination account has a login name and matches the source account login name
+		if (matchingDestAccount == null && sourceAccount.getLoginName().isPresent()) {
+			List<OsAccount> matchingDestAccounts = destinationAccounts.stream()
+					.filter(p -> p.getLoginName().isPresent())
+					.filter(p -> (p.getLoginName().get().equalsIgnoreCase(sourceAccount.getLoginName().get())
+					&& ((!sourceAccount.getAddr().isPresent()) || (!p.getAddr().isPresent()))))
+					.collect(Collectors.toList());
+			if (!matchingDestAccounts.isEmpty()) {
+				matchingDestAccount = matchingDestAccounts.get(0);
+			}
+		}
+		
+		return Optional.ofNullable(matchingDestAccount);
+	}
+	
+	/**
+	 * Checks for matching accounts in the same realm 
+	 * and then merges the accounts if a match is found
+	 * @param account The account to find matches for
+	 * @param trans The current transaction.
+	 * @throws TskCoreException 
+	 */
+	private void mergeOsAccount(OsAccount account, CaseDbTransaction trans) throws TskCoreException {
+		// Get the realm for the account
+		Long realmId = account.getRealmId();
+		OsAccountRealm realm = db.getOsAccountRealmManager().getRealmByRealmId(realmId,  trans.getConnection());
+		
+		// Get all users in the realm (excluding the account)
+		List<OsAccount> osAccounts = getOsAccounts(realm, trans.getConnection());
+		osAccounts.removeIf(acc -> Objects.equals(acc.getId(), account.getId()));
+		
+		// Look for matching account
+		Optional<OsAccount> matchingAccount = getMatchingAccountForMerge(account, osAccounts);
+		
+		// If we find a match, merge the accounts.
+		if (matchingAccount.isPresent()) {
+			mergeOsAccounts(matchingAccount.get(), account, trans);
+		}
+	}
 
 	/**
 	 * Merges data between two accounts so that only one is active at the end
@@ -958,7 +996,8 @@ private void mergeOsAccounts(OsAccount sourceAccount, OsAccount destAccount, Cas
 			s.executeUpdate(query);
 
 			
-			// TBD: We need to emit another event which tells CT that two accounts are being merged so it can updates other dedicated tables 
+			// register the merged accounts with the transaction to fire off an event
+			trans.registerMergedOsAccount(sourceAccount.getId(), destAccount.getId());
 			
 			// Update the source account. Make a dummy signature to prevent problems with the unique constraint.
 			String mergedSignature = makeMergedOsAccountSignature();
@@ -1682,6 +1721,12 @@ private OsAccountUpdateResult updateCoreWindowsOsAccountAttributes(OsAccount osA
 		String resolvedLoginName = WindowsAccountUtils.toWellknownEnglishLoginName(loginName);
 		OsAccountUpdateResult updateStatus = this.updateOsAccountCore(osAccount, accountSid, resolvedLoginName, trans);
 
+		Optional<OsAccount> updatedAccount = updateStatus.getUpdatedAccount();
+		if (updatedAccount.isPresent()) {
+			// After updating account data, check if there is matching account to merge
+			mergeOsAccount(updatedAccount.get(), trans);
+		}
+		
 		return updateStatus;
 	}
 
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 63d7a9e64063c09ec9d0b712c93bf047418499fc..1d35554c0bf6a185c3251de4cde544921a0ff8fb 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -13722,6 +13722,7 @@ public static final class CaseDbTransaction {
 		private List<Host> hostsAdded = new ArrayList<>();
 		private List<OsAccount> accountsChanged = new ArrayList<>();
 		private List<OsAccount> accountsAdded = new ArrayList<>();
+		private List<TskEvent.MergedAccountsPair> accountsMerged = new ArrayList<>();
 
 		private List<Long> deletedOsAccountObjectIds = new ArrayList<>();
 		private List<Long> deletedResultObjectIds = new ArrayList<>();
@@ -13809,6 +13810,16 @@ void registerAddedOsAccount(OsAccount account) {
 			}
 		}
 
+		/**
+		 * Saves an account that has been merged as part of this transaction.
+		 *
+		 * @param sourceOsAccountObjId
+		 * @param destinationOsAccountObjId
+		 */
+		void registerMergedOsAccount(long sourceOsAccountObjId, long destinationOsAccountObjId) {
+			accountsMerged.add(new TskEvent.MergedAccountsPair(sourceOsAccountObjId, destinationOsAccountObjId));
+		}
+
 		/**
 		 * Saves an analysis result that has been deleted as a part of this
 		 * transaction.
@@ -13885,6 +13896,9 @@ public void commit() throws TskCoreException {
 				if (!accountsChanged.isEmpty()) {
 					sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsUpdatedTskEvent(accountsChanged));
 				}
+				if (!accountsMerged.isEmpty()) {
+					sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsMergedTskEvent(accountsMerged));
+				}
 				if (!deletedOsAccountObjectIds.isEmpty()) {
 					sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsDeletedTskEvent(deletedOsAccountObjectIds));
 				}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java b/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java
index a6e193382fe73b6e7759760c5508496ee21ae3d9..da6842036cf6546fc219e4eea2c2a24587b9ff7c 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/TskEvent.java
@@ -307,6 +307,63 @@ public List<Long> getOsAccountObjectIds() {
 
 	}
 
+	/**
+	 * An event published when one or more OS accounts are merged.
+	 */
+	public final static class OsAccountsMergedTskEvent extends TskObjectsEvent<MergedAccountsPair> {
+
+		/**
+		 * Constructs an event published when one or more OS accounts are
+		 * merged.
+		 *
+		 * @param mergedAccounts List of the merged OS accounts.
+		 */
+		OsAccountsMergedTskEvent(List<MergedAccountsPair> mergedAccounts) {
+			super(mergedAccounts);
+		}
+
+
+		/**
+		 * Gets the pairs of merged accounts
+		 * 
+		 * @return 
+		 */
+		public List<MergedAccountsPair> getMergedAccountPairs() {
+			return getDataModelObjects();
+		}
+
+	}
+
+	/**
+	 * Container to encapsulate the merged account ids, contains both the source and destination account ids.
+	 */
+	public final static class MergedAccountsPair {
+
+		private final Long sourceOsAccountId;
+		private final Long destinationOsAccountId;
+
+		public MergedAccountsPair(Long sourceOsAccountId, Long destinationOsAccountId) {
+			this.sourceOsAccountId = sourceOsAccountId;
+			this.destinationOsAccountId = destinationOsAccountId;
+		}
+
+		/**
+		 * Gets the source os account id. This is the account that was marked as "MERGED"
+		 * @return The TSK object ID of the source os account
+		 */
+		public Long getSourceOsAccountId() {
+			return sourceOsAccountId;
+		}
+
+		/**
+		 * Gets the destination os account id. This is the account that the source was merged into.
+		 * @return The TSK object ID of the destination os account
+		 */
+		public Long getDestinationOsAccountId() {
+			return destinationOsAccountId;
+		}
+	}
+	
 	/**
 	 * An event published when one or more OS account instances are added.
 	 */
diff --git a/bindings/java/test/org/sleuthkit/datamodel/OsAccountTest.java b/bindings/java/test/org/sleuthkit/datamodel/OsAccountTest.java
index 8f3e373d06af979f7000d9aee5d566fe724f0cc2..b18826c9b745bdaad566dd51e4270b7be1dc0bcb 100644
--- a/bindings/java/test/org/sleuthkit/datamodel/OsAccountTest.java
+++ b/bindings/java/test/org/sleuthkit/datamodel/OsAccountTest.java
@@ -396,6 +396,87 @@ public void mergeRealmsTests() throws TskCoreException, OsAccountManager.NotUser
 		}
 	}
 	
+	@Test 
+	public void updateRealmAndMergeTests() throws TskCoreException, OsAccountManager.NotUserSIDException {
+		
+		/**
+		 * Test the scenario where an update of an account triggers an update of 
+		 * a realm and subsequent merge of realms and accounts.
+		 */
+		
+		Host host = caseDB.getHostManager().newHost("updateRealmAndMergeTestHost");
+		
+		
+		
+			// Step 1: create a local account with SID and user name
+			String ownerUid1 = "S-1-5-21-1182664808-117526782-2525957323-13395";
+			String realmName1 = null;
+			String loginName1 = "sandip";
+			
+			OsAccount osAccount1 = caseDB.getOsAccountManager().newWindowsOsAccount(ownerUid1, loginName1, realmName1, host, OsAccountRealm.RealmScope.LOCAL);
+			OsAccountRealm realm1 = caseDB.getOsAccountRealmManager().getRealmByRealmId(osAccount1.getRealmId());
+			
+			assertEquals(realm1.getRealmAddr().isPresent(), true);	// verify the realm has a SID
+			assertEquals(realm1.getRealmNames().isEmpty(), true);	// verify the realm has no name
+			
+			
+			// Step2: create a local account with domain name and username
+			String ownerUid2 = null;
+			String realmName2 = "CORP";
+			String loginName2 = "sandip";
+			
+			Optional<OsAccount> oOsAccount2 = caseDB.getOsAccountManager().getWindowsOsAccount(ownerUid2, loginName2, realmName2, host);
+			
+			// this account should not exists
+			assertEquals(oOsAccount2.isPresent(), false);
+			
+			// create a new account -  a new realm as there is nothing to tie it to realm1 
+			OsAccount osAccount2 = caseDB.getOsAccountManager().newWindowsOsAccount(ownerUid2, loginName2, realmName2, host, OsAccountRealm.RealmScope.LOCAL);
+			OsAccountRealm realm2 = caseDB.getOsAccountRealmManager().getRealmByRealmId(osAccount2.getRealmId());
+			
+			assertTrue(osAccount1.getId() != osAccount2.getId());
+			assertTrue(realm1.getRealmId() != realm2.getRealmId());
+			
+			
+			
+			// Step 3: now create/update the account with sid/domain/username
+			// this should return the existing account1, which needs to be updated.
+			String ownerUid3 = "S-1-5-21-1182664808-117526782-2525957323-13395";
+			String realmAddr3 = "S-1-5-21-1182664808-117526782-2525957323";
+			String loginName3 = "sandip";
+			String realmName3 = "CORP";
+			
+			Optional<OsAccount> oOsAccount3 = caseDB.getOsAccountManager().getWindowsOsAccount(ownerUid3, loginName3, realmName3, host);
+
+			assertTrue(oOsAccount3.isPresent());
+			
+            
+			// update the account so that its domain gets updated.
+			OsAccountManager.OsAccountUpdateResult updateResult = caseDB.getOsAccountManager().updateCoreWindowsOsAccountAttributes(oOsAccount3.get(), ownerUid3, loginName3, realmName3, host);
+			Optional<OsAccount> updatedAccount3 = updateResult.getUpdatedAccount();
+			assertTrue(updatedAccount3.isPresent());
+
+			// this should cause the realm1 to be updated - and then realm2 to be merged into realm1 
+			OsAccountRealm realm3 = caseDB.getOsAccountRealmManager().getRealmByRealmId(updatedAccount3.get().getRealmId());
+
+			assertTrue(realm3.getRealmId() == realm1.getRealmId());
+
+			assertTrue(realm3.getRealmAddr().isPresent());		// verify the realm gets an addr
+			assertTrue(realm3.getRealmAddr().get().equalsIgnoreCase(realmAddr3));
+			
+			assertTrue(realm3.getRealmNames().get(0).equalsIgnoreCase(realmName3));	// verify realm name.
+
+
+			// And now verify that the realm2 has been merged into realm1. 
+			OsAccountRealm realm22 = caseDB.getOsAccountRealmManager().getRealmByRealmId(osAccount2.getRealmId());
+			assertTrue(realm22.getDbStatus() == OsAccountRealm.RealmDbStatus.MERGED);
+
+			//and account2 has been merged into account1
+			OsAccount osAccount22 = caseDB.getOsAccountManager().getOsAccountByObjectId(osAccount2.getId());
+			assertTrue(osAccount22.getOsAccountDbStatus() == OsAccount.OsAccountDbStatus.MERGED);
+				
+	}
+	
 	@Test 
 	public void hostAddressTests() throws TskCoreException {
 		
@@ -1193,11 +1274,43 @@ public void windowsAccountUpdateTests() throws TskCoreException, OsAccountManage
 		assertTrue(updatedAccount2.getLoginName().orElse("").equalsIgnoreCase(loginname2));
 		assertTrue(updatedAccount2.getSignature().equalsIgnoreCase(ownerUid2));	// account signature should now be addr
 		
-		// RAMAN TODO: CT-4284
-//		OsAccountRealm realm2 = caseDB.getOsAccountRealmManager().getRealmByRealmId(updatedAccount2.getRealmId());
-//		assertTrue(realm2.getRealmAddr().orElse("").equalsIgnoreCase(realmAddr1));
-//		assertTrue(realm2.getSignature().equalsIgnoreCase(realmSignature1));	
+		OsAccountRealm realm2 = caseDB.getOsAccountRealmManager().getRealmByRealmId(updatedAccount2.getRealmId());
+		assertTrue(realm2.getRealmAddr().orElse("").equalsIgnoreCase(realmAddr1));
+		assertTrue(realm2.getSignature().equalsIgnoreCase(realmSignature1));
 	}
 	
+	@Test
+	public void windowsAccountMergeTests() throws TskCoreException, OsAccountManager.NotUserSIDException {
+
+		String hostname1 = "windowsAccountMergeTestHost";
+		Host host1 = caseDB.getHostManager().newHost(hostname1);
 	
+		// 1. Create an account with a SID alone
+		String sid = "S-1-5-21-111111111-222222222-666666666-0001";
+		OsAccount osAccount1 = caseDB.getOsAccountManager().newWindowsOsAccount(sid, null, null, host1, OsAccountRealm.RealmScope.LOCAL);
+		
+		Long realmId = osAccount1.getRealmId();
+		
+		// 2. Create an account with loginName and realmName
+		String loginName = "jdoe";
+		String realmName = "testRealm";
+		OsAccount osAccount2 = caseDB.getOsAccountManager().newWindowsOsAccount(null, loginName, realmName, host1, OsAccountRealm.RealmScope.LOCAL);
+
+		// 3. Lookup account by SID, loginName, and realmName
+		Optional<OsAccount> oOsAccount = caseDB.getOsAccountManager().getWindowsOsAccount(sid, loginName, realmName, host1);
+		assertTrue(oOsAccount.isPresent());
+		
+		// 4. Update this account with all SID, loginName, and realmName
+		caseDB.getOsAccountManager().updateCoreWindowsOsAccountAttributes(oOsAccount.get(), sid, loginName, realmName, host1);
+		
+		// The two accounts should be merged
+		
+		// Test that there is now only one account associated with sid1
+		List<OsAccount> accounts = caseDB.getOsAccountManager().getOsAccounts().stream().filter(a -> a.getAddr().isPresent() && a.getAddr().get().equals(sid)).collect(Collectors.toList());
+		assertEquals(accounts.size() == 1, true);
+		
+		// Test that there is now only one account associated with loginName
+		accounts = caseDB.getOsAccountManager().getOsAccounts().stream().filter(p -> p.getLoginName().isPresent() && p.getLoginName().get().equals(loginName)).collect(Collectors.toList());
+		assertEquals(accounts.size() == 1, true);
+	}
 }
diff --git a/tsk/fs/logical_fs.cpp b/tsk/fs/logical_fs.cpp
index 68c98b1c2a22503a02fc748e0374c31171956aa1..897c465645545187f421045d5e894de477ca5c30 100644
--- a/tsk/fs/logical_fs.cpp
+++ b/tsk/fs/logical_fs.cpp
@@ -321,7 +321,7 @@ TSK_TCHAR * create_search_path_long_path(const TSK_TCHAR *base_path) {
 	return searchPath;
 #else
 	// Nothing to do here if it's not Windows
-	return null;
+	return NULL;
 #endif
 }