Potresti mantenere filiali separate per ogni cliente e unire le modifiche dal tuo trunk, proprio come  dbb  sta dicendo. Tuttavia, esiste un buon modo per farlo e un modo sbagliato in cui tutto ciò diventa complicato e rapidamente fuori controllo se esistono molte funzionalità simili condivise tra più clienti. 
 Il modo più semplice per gestire le varianti,  ciascuna per ogni cliente , è attraverso  ramificazione per astrazione  anziché. In poche parole: crea la gestione della configurazione nell'applicazione / sistema che attiva e disattiva la funzionalità richiesta dai clienti. In questo modo non devi preoccuparti di unire il controllo del codice sorgente. Può essere complesso come un sistema plug-in, ma puoi farlo semplicemente avendo una funzione nel tuo programma che passa attraverso un file di configurazione e abilita la funzionalità di cui hai bisogno. 
 Come costruirlo dipende da quale ambiente lo stai sviluppando. Java ha una classe  Proprietà  che può farlo per te. In C # puoi cercare  qui  per maggiori informazioni. Sebbene sia possibile codificare in modo rigido queste proprietà con una switch-case o una mappa hash e gestire le differenze di questa classe di configurazione tramite il controllo del codice sorgente, nel caso in cui non si desideri che i clienti riconfigurino facilmente il software. 
 Esempi in Java: 
  Leggi un file di configurazione con   java.util.Properties     
 Fonte: 
public class ReadConfig {
    private static final CONFIG_FILEPATH = "config.txt";
    private Properties config;
    public ReadConfig() {
        config = new Properties();
        config.load(CONFIG_FILEPATH);
    }
    public boolean isEnabled(String functionality) {
        String s = config.getProperty(functionality);
        return Boolean.getBoolean(s);
    }
}
 Contenuto di   config.txt    (che può essere gestito per ogni cliente): 
Eat_Sandwich: true
Make_Sandwich: false
 Esempio di utilizzo: 
public static void main(String[] args) {
    ReadConfig myConfig = new ReadConfig();
    if(myConfig.isEnabled("Eat_Sandwich")) {
        System.out.println("I can eat the sandwich");
    }
    if(myConfig.isEnabled("Make_Sandwich")) {
        System.out.println("I can make the sandwich");
    }
}
// Will output: I can eat the sandwich
  Codice hard della configurazione  
 Origine (che può essere gestita per ogni cliente): 
public class HardCodedConfig {
    private HashMap<String, Boolean> config;
    public HardCodedConfig() {
        config = new HashMap<String, Boolean>();
        // Add functionalities here:
        register("Make_Sandwich", true);
        register("Eat_Sandwich", false);
    }
    private void register(String functionality, boolean enabled) {
        config.put(functionality, enabled);
    }
    private boolean isEnabled(String functionality) {
        return config.get(functionality);
    }
}
 Utilizzo: 
public static void main(String[] args) {
    HardCodedConfig myConfig = new HardCodedConfig();
    if(myConfig.isEnabled("Eat_Sandwich")) {
        System.out.println("I can eat the sandwich");
    }
    if(myConfig.isEnabled("Make_Sandwich")) {
        System.out.println("I can make the sandwich");
    }
}
// Will output: I can make the sandwich
  EDIT:  
 Dato che l'OP vuole qualcosa di un po 'più avanzato rispetto all'attivazione delle funzionalità, è possibile farlo attraverso il caricamento delle librerie. Ma dovresti fare attenzione ad aggiungere librerie esterne (come dll e jar) nel repository di origine, dato che ti farebbe un lavoro extra di pulizia della casa da fare. Quindi se hai file che possono essere generati tramite script di compilazione (usi un  build server , giusto?), Allora non includile nel controllo del codice sorgente. 
 Invece, tieni traccia delle diverse DLL che devi compilare e utilizzare tramite gli script di configurazione configurabili, in modo da poter creare l'applicazione da zero insieme ai programmi di installazione per ciascun cliente. 
 Considera anche l'utilizzo di modelli come il  Pattern di strategia , per separare diverse implementazioni della stessa funzionalità. Nel tuo esempio, calcolare gli sconti, può essere fatto creando un'interfaccia e / o una classe astratta. Ecco una semplice implementazione in C #: 
public interface IDiscountStrategy {
    /**
     * Calculates the discount from amount
     */
    public decimal calculateDiscount(decimal amount);
}
public class DefaultDiscountStrategy : IDiscountStrategy {
    public decimal _percentage;
    public DefaultDiscountStrategy(decimal percentage) {
        _percentage = percentage;
    }
    public decimal calculateDiscount(decimal amount) {
        return amount * _percentage;
    }
}
 L'utilizzo è chiamare il metodo   calculateDiscount    su DiscountStrategy che è stato caricato. 
 Nella tua libreria dll separata per un cliente specifico hai il seguente che viene usato invece quando l'applicazione carica: 
public class WeirdCustomerDiscountStrategy : IDiscountStrategy {
    public decimal calculateDiscount(decimal amount) {
        DayOfWeek dayOfWeek = DateTime.Now.DayOfWeek;
        if (dayOfWeek == DayOfWeek.Thursday)
            return amount * 0.05;
        else
            return 0;
    }
}
 Nella tua applicazione comune caricherete le diverse strategie in questo modo: 
public IDiscountStrategy getDiscountStrategy() {
    Assembly assembly;
    try {
        assembly = Assembly.LoadFrom("CustomerXYZ.dll");
    } catch (FileNotFoundException e) {
        assembly = null;
    }
    IDiscountStrategy discounter;
    if (assembly == null) {
        discounter = new DefaultDiscountStrategy(0.10);
    } else { 
        discounter = (IDiscountStrategy) 
            assembly.CreateInstance("WeirdCustomerDiscountStrategy");
    }
    return discounter;
}
 Diventa piuttosto peloso quando l'applicazione cresce. Quindi potresti prendere in considerazione l'idea di utilizzare un framework IoC per farlo, ad esempio  StructureMap  o autofaq  se utilizzi .NET o  Spring  se stanno usando Java. Ecco un  esempio di "plug-in scanner" in StructureMap .