diff --git a/main.go b/main.go
index 119cc45..4ff177c 100644
--- a/main.go
+++ b/main.go
@@ -16,30 +16,37 @@ import (
 )
 
 type FileQuality struct {
-	Path     string
-	Bitrate  int
-	Bitdepth int
-	Size     int64
+	Path         string
+	Bitrate      int
+	Bitdepth     int
+	Size         int64
+	ReleaseID    string // MusicBrainz release ID or other unique identifier
+	ReleaseYear  string // Release year from metadata
+	CatalogNum   string // Catalog number
+	ReleaseInfo  string // Human-readable release info for logging
 }
 
 var (
 	logFile    *os.File
 	armed      bool
 	dryRun     bool
+	forceMode  bool // Force processing even if releases appear different
 	logWriter  *bufio.Writer
-	version    = "1.0.0"
+	version    = "1.1.0"
 	dateFormat = "2006-01-02 15:04:05"
 )
 
 func init() {
 	flag.BoolVar(&armed, "armed", false, "Enable actual file operations (rename/delete)")
 	flag.BoolVar(&dryRun, "dry-run", false, "Simulate operations without making changes")
+	flag.BoolVar(&forceMode, "force", false, "Force processing even if releases appear different")
 	flag.Usage = func() {
 		fmt.Fprintf(flag.CommandLine.Output(), "FLAC Duplicate Cleaner v%s\n", version)
 		fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] [directory]\n", os.Args[0])
 		flag.PrintDefaults()
 		fmt.Println("\nBy default, runs in dry-run mode showing what would be done")
 		fmt.Println("Specify -armed to actually perform operations")
+		fmt.Println("Use -force to process files even if they appear to be from different releases")
 	}
 }
 
@@ -67,12 +74,12 @@ func getCurrentTime() string {
 	return time.Now().Format(dateFormat)
 }
 
-func getMediaInfo(filePath string) (int, int, error) {
+func getMediaInfo(filePath string) (int, int, string, string, string, error) {
 	// Get bitrate
 	bitrateCmd := exec.Command("mediainfo", "--Output=Audio;%BitRate%", filePath)
 	bitrateOut, err := bitrateCmd.Output()
 	if err != nil {
-		return 0, 0, fmt.Errorf("mediainfo bitrate failed: %w", err)
+		return 0, 0, "", "", "", fmt.Errorf("mediainfo bitrate failed: %w", err)
 	}
 	bitrateStr := strings.TrimSpace(string(bitrateOut))
 	bitrate, err := strconv.Atoi(bitrateStr)
@@ -84,7 +91,7 @@ func getMediaInfo(filePath string) (int, int, error) {
 	bitdepthCmd := exec.Command("mediainfo", "--Output=Audio;%BitDepth%", filePath)
 	bitdepthOut, err := bitdepthCmd.Output()
 	if err != nil {
-		return 0, 0, fmt.Errorf("mediainfo bitdepth failed: %w", err)
+		return 0, 0, "", "", "", fmt.Errorf("mediainfo bitdepth failed: %w", err)
 	}
 	bitdepthStr := strings.TrimSpace(string(bitdepthOut))
 	bitdepth, err := strconv.Atoi(bitdepthStr)
@@ -92,7 +99,50 @@ func getMediaInfo(filePath string) (int, int, error) {
 		bitdepth = 0
 	}
 
-	return bitrate, bitdepth, nil
+	// Get MusicBrainz release ID
+	releaseIDCmd := exec.Command("mediainfo", "--Output=General;%MUSICBRAINZ_RELEASETRACKID%", filePath)
+	releaseIDOut, err := releaseIDCmd.Output()
+	var releaseID string
+	if err == nil {
+		releaseID = strings.TrimSpace(string(releaseIDOut))
+	}
+
+	// Get release year
+	yearCmd := exec.Command("mediainfo", "--Output=General;%Released_Date%", filePath)
+	yearOut, err := yearCmd.Output()
+	var year string
+	if err == nil {
+		year = strings.TrimSpace(string(yearOut))
+		// If no released date, try recorded date
+		if year == "" {
+			yearCmd = exec.Command("mediainfo", "--Output=General;%Recorded_Date%", filePath)
+			yearOut, err := yearCmd.Output()
+			if err == nil {
+				year = strings.TrimSpace(string(yearOut))
+			}
+		}
+		// Extract just the year if it's a full date
+		if len(year) >= 4 {
+			year = year[0:4]
+		}
+	}
+
+	// Get catalog number
+	catalogCmd := exec.Command("mediainfo", "--Output=General;%CATALOGNUMBER%", filePath)
+	catalogOut, err := catalogCmd.Output()
+	var catalogNum string
+	if err == nil {
+		catalogNum = strings.TrimSpace(string(catalogOut))
+	}
+
+	return bitrate, bitdepth, releaseID, year, catalogNum, nil
+}
+
+func getReleaseInfo(filePath string) string {
+	// Get a summary of release info for logging
+	infoCmd := exec.Command("mediainfo", "--Output=General;Album: %Album%, Released: %Released_Date%, Recorded: %Recorded_Date%, Label: %Label%, CatalogNum: %CATALOGNUMBER%", filePath)
+	infoOut, _ := infoCmd.Output()
+	return strings.TrimSpace(string(infoOut))
 }
 
 func findDuplicateFiles(rootDir string) (map[string][]FileQuality, error) {
@@ -162,74 +212,143 @@ func bytesToHumanReadable(bytes int64) string {
 	return fmt.Sprintf("%.1f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp])
 }
 
-func processFileGroup(baseFile string, files []FileQuality) {
+func processFileGroup(baseFile string, files []FileQuality) (int64, bool) {
 	writeLog(fmt.Sprintf("Processing group for: %s", baseFile))
+	processed := false
+	var spaceRecovered int64 = 0
 
 	// Get quality info for all files
 	var bestFile FileQuality
 	var totalSize int64
+	releaseMap := make(map[string][]FileQuality)
 
 	for i := range files {
-		bitrate, bitdepth, err := getMediaInfo(files[i].Path)
+		bitrate, bitdepth, releaseID, year, catalogNum, err := getMediaInfo(files[i].Path)
 		if err != nil {
 			writeLog(fmt.Sprintf("  - Error getting media info for %s: %v", files[i].Path, err))
 			continue
 		}
 		files[i].Bitrate = bitrate
 		files[i].Bitdepth = bitdepth
+		files[i].ReleaseID = releaseID
+		files[i].ReleaseYear = year
+		files[i].CatalogNum = catalogNum
+		files[i].ReleaseInfo = getReleaseInfo(files[i].Path)
 		totalSize += files[i].Size
 
-		writeLog(fmt.Sprintf("  - Found: %s (Bitrate: %d, Bitdepth: %d, Size: %d bytes)",
-			files[i].Path, files[i].Bitrate, files[i].Bitdepth, files[i].Size))
-
-		// Determine the best file using quality then size as tiebreaker
-		if files[i].Bitrate > bestFile.Bitrate ||
-			(files[i].Bitrate == bestFile.Bitrate && files[i].Bitdepth > bestFile.Bitdepth) ||
-			(files[i].Bitrate == bestFile.Bitrate && files[i].Bitdepth == bestFile.Bitdepth && files[i].Size > bestFile.Size) {
-			bestFile = files[i]
+		// Create a unique key for grouping by release
+		releaseKey := releaseID
+		if releaseKey == "" {
+			// Fallback if no MusicBrainz ID
+			releaseKey = fmt.Sprintf("%s-%s", year, catalogNum)
 		}
+
+		releaseMap[releaseKey] = append(releaseMap[releaseKey], files[i])
+
+		writeLog(fmt.Sprintf("  - Found: %s (Bitrate: %d, Bitdepth: %d, Size: %s, Year: %s, CatalogNum: %s)",
+			files[i].Path, files[i].Bitrate, files[i].Bitdepth, 
+			bytesToHumanReadable(files[i].Size), files[i].ReleaseYear, files[i].CatalogNum))
+		writeLog(fmt.Sprintf("    Release info: %s", files[i].ReleaseInfo))
 	}
 
-	if bestFile.Path == "" {
-		writeLog("  - No valid files found in group")
-		return
-	}
-
-	writeLog(fmt.Sprintf("  -> Keeping: %s (Bitrate: %d, Bitdepth: %d, Size: %d bytes)",
-		bestFile.Path, bestFile.Bitrate, bestFile.Bitdepth, bestFile.Size))
-
-	// Rename best file to original name if it's not already
-	if bestFile.Path != baseFile {
-		action := "Would rename"
-		if armed && !dryRun {
-			action = "Renaming"
-			err := os.Rename(bestFile.Path, baseFile)
-			if err != nil {
-				writeLog(fmt.Sprintf("    ! Rename failed: %v", err))
-				return
+	// Check if files are from different releases
+	if len(releaseMap) > 1 && !forceMode {
+		writeLog("  ! Files appear to be from different releases. Skipping group (use -force to override).")
+		for releaseKey, releaseFiles := range releaseMap {
+			writeLog(fmt.Sprintf("    Release group: %s", releaseKey))
+			for _, file := range releaseFiles {
+				writeLog(fmt.Sprintf("      - %s", file.Path))
 			}
 		}
-		writeLog(fmt.Sprintf("  * %s: %s -> %s", action, bestFile.Path, baseFile))
-		bestFile.Path = baseFile
+		return 0, false
 	}
 
-	// Delete other files
-	for _, file := range files {
-		if file.Path != bestFile.Path {
-			action := "Would delete"
+	// Process each release group
+	for releaseKey, releaseFiles := range releaseMap {
+		if len(releaseFiles) <= 1 {
+			// Skip if only one file for this release
+			continue
+		}
+
+		writeLog(fmt.Sprintf("  Processing release group: %s", releaseKey))
+		bestFile = FileQuality{}
+		
+		// Find best file for this release
+		for _, file := range releaseFiles {
+			// Determine the best file using quality then size as tiebreaker
+			if file.Bitrate > bestFile.Bitrate ||
+				(file.Bitrate == bestFile.Bitrate && file.Bitdepth > bestFile.Bitdepth) ||
+				(file.Bitrate == bestFile.Bitrate && file.Bitdepth == bestFile.Bitdepth && file.Size > bestFile.Size) {
+				bestFile = file
+			}
+		}
+
+		if bestFile.Path == "" {
+			writeLog("    - No valid files found in this release group")
+			continue
+		}
+
+		writeLog(fmt.Sprintf("  -> Keeping: %s (Bitrate: %d, Bitdepth: %d, Size: %s)",
+			bestFile.Path, bestFile.Bitrate, bestFile.Bitdepth, bytesToHumanReadable(bestFile.Size)))
+
+		// If this is the primary file (without (n) in name), make sure the best quality version is it
+		isBaseFile := (bestFile.Path == baseFile || 
+		               strings.TrimSuffix(bestFile.Path, ".flac") == strings.TrimSuffix(baseFile, ".flac"))
+		
+		// Generate target filename
+		targetFilename := baseFile
+		if !isBaseFile && len(releaseMap) > 1 {
+			// For multiple releases, append year/identifier to filename to avoid conflicts
+			ext := filepath.Ext(baseFile)
+			baseName := strings.TrimSuffix(baseFile, ext)
+			
+			// Use year or catalog number as identifier
+			identifier := bestFile.ReleaseYear
+			if identifier == "" && bestFile.CatalogNum != "" {
+				identifier = bestFile.CatalogNum
+			}
+			
+			if identifier != "" {
+				targetFilename = fmt.Sprintf("%s [%s]%s", baseName, identifier, ext)
+			}
+		}
+
+		// Rename best file to target name if needed
+		if bestFile.Path != targetFilename {
+			action := "Would rename"
 			if armed && !dryRun {
-				action = "Deleting"
-				err := os.Remove(file.Path)
+				action = "Renaming"
+				err := os.Rename(bestFile.Path, targetFilename)
 				if err != nil {
-					writeLog(fmt.Sprintf("    ! Delete failed for %s: %v", file.Path, err))
+					writeLog(fmt.Sprintf("    ! Rename failed: %v", err))
 					continue
 				}
 			}
-			writeLog(fmt.Sprintf("  * %s: %s (Recovering %s)", action, file.Path, bytesToHumanReadable(file.Size)))
+			writeLog(fmt.Sprintf("  * %s: %s -> %s", action, bestFile.Path, targetFilename))
+			bestFile.Path = targetFilename
+		}
+
+		// Delete other files in this release group
+		for _, file := range releaseFiles {
+			if file.Path != bestFile.Path {
+				action := "Would delete"
+				if armed && !dryRun {
+					action = "Deleting"
+					err := os.Remove(file.Path)
+					if err != nil {
+						writeLog(fmt.Sprintf("    ! Delete failed for %s: %v", file.Path, err))
+						continue
+					}
+				}
+				writeLog(fmt.Sprintf("  * %s: %s (Recovering %s)", action, file.Path, bytesToHumanReadable(file.Size)))
+				spaceRecovered += file.Size
+				processed = true
+			}
 		}
 	}
 
-	writeLog(fmt.Sprintf("  Total recoverable space: %s", bytesToHumanReadable(totalSize-bestFile.Size)))
+	writeLog(fmt.Sprintf("  Total potentially recoverable space: %s", bytesToHumanReadable(spaceRecovered)))
+	return spaceRecovered, processed
 }
 
 func main() {
@@ -262,6 +381,9 @@ func main() {
 	} else {
 		writeLog("ARMED MODE: Files will be renamed and deleted!")
 	}
+	if forceMode {
+		writeLog("FORCE MODE: Will process even if releases appear different!")
+	}
 	writeLog("===============================")
 
 	// Check mediainfo is available
@@ -285,17 +407,18 @@ func main() {
 	}
 
 	var totalRecoverableSpace int64
+	processedGroups := 0
 
 	for baseFile, group := range fileGroups {
-		processFileGroup(baseFile, group)
-		for _, file := range group {
-			if file.Path != baseFile {
-				totalRecoverableSpace += file.Size
-			}
+		spaceRecovered, processed := processFileGroup(baseFile, group)
+		if processed {
+			processedGroups++
+			totalRecoverableSpace += spaceRecovered
 		}
 		writeLog("")
 	}
 
+	writeLog(fmt.Sprintf("Processed %d of %d file groups", processedGroups, len(fileGroups)))
 	writeLog(fmt.Sprintf("Total recoverable space: %s", bytesToHumanReadable(totalRecoverableSpace)))
 	writeLog(fmt.Sprintf("Cleanup completed at %s", getCurrentTime()))
 	writeLog("===============================")