@Override
	public void merge(TaskMonitor monitor) {
		mergeManager.setInProgress(PROGRAM_TREE_PHASE);
		// For now this method simply does a coarse increment of the progress bar for the current phase.

		this.currentMonitor = monitor;
		long[] myChangeIDs = myChangeSet.getProgramTreeChanges();
		long[] myIDsAdded = myChangeSet.getProgramTreeAdditions();

		long[] latestChangeIDs = latestChangeSet.getProgramTreeChanges();
		long[] latestIDsAdded = latestChangeSet.getProgramTreeAdditions();

		mergeManager.updateProgress(0,
			"Program Tree Merge is processing IDs changed in Checked Out...");
		ArrayList<Long> changeList = new ArrayList<Long>();
		for (long myChangeID : myChangeIDs) {
			changeList.add(Long.valueOf(myChangeID));
		}

		mergeManager.updateProgress(10,
			"Program Tree Merge is processing IDs added in Checked Out...");
		ArrayList<Long> myAddedList = new ArrayList<Long>();
		for (long element : myIDsAdded) {
			myAddedList.add(Long.valueOf(element));
		}

		mergeManager.updateProgress(20, "Program Tree Merge is eliminating removed IDs...");
		// remove Added IDs from changed IDs
		changeList.removeAll(myAddedList);

		mergeManager.updateProgress(30, "Program Tree Merge is processing IDs added in Latest...");
		ArrayList<Long> latestAddedList = new ArrayList<Long>();
		for (long element : latestIDsAdded) {
			latestAddedList.add(Long.valueOf(element));
		}

		conflictsChangeList = new ArrayList<Long>(changeList);

		mergeManager.updateProgress(40, "Program Tree Merge is processing change IDs...");
		ArrayList<Long> latestChangeList = new ArrayList<Long>();
		for (long latestChangeID : latestChangeIDs) {
			latestChangeList.add(Long.valueOf(latestChangeID));
		}

		mergeManager.updateProgress(50,
			"Program Tree Merge is finding changes to apply automatically...");
		//	automatic = my changes - latest changes
		changeList.removeAll(latestChangeList);

		mergeManager.updateProgress(60, "Program Tree Merge is finding conflicting IDs...");
		// get conflicting IDs
		conflictsChangeList.retainAll(latestChangeList);

		monitor.setMaximum(myAddedList.size() + changeList.size() + conflictsChangeList.size());
		int transactionID = resultProgram.startTransaction("Merge Program Trees");
		boolean commit = false;
		try {

			mergeManager.updateProgress(70, "Program Tree Merge is applying additions...");
			// apply additions of new trees
			applyAdditions(myAddedList);

			mergeManager.updateProgress(80, "Program Tree Merge is applying changes...");
			applyChanges(changeList);

			mergeManager.updateProgress(90, "Program Tree Merge is processing conflicts...");
			processConflicts(conflictsChangeList);

			mergeManager.updateProgress(100, "Done merging program trees");
			commit = true;

		}
		catch (CancelledException e) {
		}
		finally {
			resultProgram.endTransaction(transactionID, commit);
		}
		mergeManager.setCompleted(PROGRAM_TREE_PHASE);
	}
Construct a new manager for merging trees
@param mergeManager the program merge manager
@param resultProgram latest version of the Program that is the 
destination for changes applied from the source program
@param myProgram source of changes to apply to the destination
program
@param originalProgram program that was originally checked out
@param latestProgram program that is the latest version; the
resultProgram and latestProgram start out as being identical
@param latestChangeSet change set of the destination program
@param myChangeSet change set for the source program
Ghidra/Features/Base/src/main/java/ghidra/app/merge/tree/ProgramTreeMergeManager.java