diff --git a/commerce_discount.info b/commerce_discount.info
index 5da9a6c..e7a6942 100644
--- a/commerce_discount.info
+++ b/commerce_discount.info
@@ -7,6 +7,9 @@ dependencies[] = number
 dependencies[] = entity
 dependencies[] = entityreference
 dependencies[] = inline_entity_form (>=1.5)
+dependencies[] = list
+dependencies[] = options
+dependencies[] = text
 dependencies[] = views
 dependencies[] = commerce
 dependencies[] = commerce_price
diff --git a/commerce_discount.install b/commerce_discount.install
index 2a10402..10dadc1 100644
--- a/commerce_discount.install
+++ b/commerce_discount.install
@@ -152,8 +152,8 @@ function commerce_discount_install_helper() {
     $field_types = field_info_field_types();
   }
 
+  // Create the discount offer entity reference field for use on all discounts.
   if (empty($fields['commerce_discount_offer']) && isset($field_types['entityreference'])) {
-    // Create entity reference field.
     $field = array(
       'entity_types' => array('commerce_discount'),
       'settings' => array(
@@ -171,6 +171,43 @@ function commerce_discount_install_helper() {
     );
     field_create_field($field);
   }
+
+  // Create the discount compatibility strategy field for use on all discounts.
+  if (empty($fields['commerce_compatibility_strategy'])) {
+    $field = array(
+      'type' => 'list_text',
+      'field_name' => 'commerce_compatibility_strategy',
+      'locked' => TRUE,
+      'settings' => array(
+        'allowed_values' => array(),
+        'allowed_values_function' => 'commerce_discount_compatibility_strategies',
+      ),
+    );
+    field_create_field($field);
+  }
+
+  // Create the selected discounts field for use on all discounts.
+  if (empty($fields['commerce_compatibility_selection'])) {
+    $field = array(
+      'type' => 'entityreference',
+      'field_name' => 'commerce_compatibility_selection',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'locked' => TRUE,
+      'settings' => array(
+        'target_type' => 'commerce_discount',
+        'handler' => 'base',
+        'handler_settings' => array(
+          'sort' => array(
+            'type' => 'property',
+            'property' => 'label',
+            'direction' => 'ASC',
+          ),
+        ),
+      ),
+    );
+    field_create_field($field);
+  }
+
   if (empty($fields['commerce_fixed_amount'])) {
     // Add price field to the commerce discount offer "fixed_amount" bundle.
     $field = array(
@@ -285,7 +322,41 @@ function commerce_discount_install_helper() {
       );
       field_create_instance($instance);
     }
+    if (empty($instances['commerce_discount'][$type]['commerce_compatibility_strategy'])) {
+      $instance = array(
+        'field_name' => 'commerce_compatibility_strategy',
+        'label' => t('Compatibility with other discounts'),
+        'entity_type' => 'commerce_discount',
+        'bundle' => $type,
+        'required' => TRUE,
+        'widget' => array(
+          'weight' => -10,
+          'type' => 'options_buttons',
+          'module' => 'options',
+        ),
+        'default_value' => array(
+          0 => array('value' => 'any'),
+        ),
+      );
+      field_create_instance($instance);
+    }
+    if (empty($instances['commerce_discount'][$type]['commerce_compatibility_selection'])) {
+      $instance = array(
+        'field_name' => 'commerce_compatibility_selection',
+        'label' => t('Selected discounts'),
+        'entity_type' => 'commerce_discount',
+        'bundle' => $type,
+        'required' => FALSE,
+        'widget' => array(
+          'weight' => -9,
+          'type' => 'entityreference_autocomplete',
+          'module' => 'entityreference',
+        ),
+      );
+      field_create_instance($instance);
+    }
   }
+
   if (empty($instances['commerce_discount_offer']['fixed_amount']['commerce_fixed_amount'])) {
     $instance = array(
       'field_name' => 'commerce_fixed_amount',
@@ -528,3 +599,88 @@ function commerce_discount_update_7105() {
 
   return t('Sort order added to the Commerce Discount table.');
 }
+
+/**
+ * Add discount compatibility fields to all discount types.
+ */
+function commerce_discount_update_7106() {
+  $fields = field_read_fields(array(), array('include_inactive' => TRUE));
+
+  // Create the discount compatibility strategy field for use on all discounts.
+  if (empty($fields['commerce_compatibility_strategy'])) {
+    $field = array(
+      'type' => 'list_text',
+      'field_name' => 'commerce_compatibility_strategy',
+      'locked' => TRUE,
+      'settings' => array(
+        'allowed_values' => array(),
+        'allowed_values_function' => 'commerce_discount_compatibility_strategies',
+      ),
+    );
+    field_create_field($field);
+  }
+
+  // Create the selected discounts field for use on all discounts.
+  if (empty($fields['commerce_compatibility_selection'])) {
+    $field = array(
+      'type' => 'entityreference',
+      'field_name' => 'commerce_compatibility_selection',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'locked' => TRUE,
+      'settings' => array(
+        'target_type' => 'commerce_discount',
+        'handler' => 'base',
+        'handler_settings' => array(
+          'sort' => array(
+            'type' => 'property',
+            'property' => 'label',
+            'direction' => 'ASC',
+          ),
+        ),
+      ),
+    );
+    field_create_field($field);
+  }
+
+  field_sync_field_status();
+  field_info_cache_clear();
+  $instances = field_info_instances();
+
+  foreach (commerce_discount_types() as $type => $value) {
+    if (empty($instances['commerce_discount'][$type]['commerce_compatibility_strategy'])) {
+      $instance = array(
+        'field_name' => 'commerce_compatibility_strategy',
+        'label' => t('Compatibility with other discounts'),
+        'entity_type' => 'commerce_discount',
+        'bundle' => $type,
+        'required' => TRUE,
+        'widget' => array(
+          'weight' => -10,
+          'type' => 'options_buttons',
+          'module' => 'options',
+        ),
+        'default_value' => array(
+          0 => array('value' => 'any'),
+        ),
+      );
+      field_create_instance($instance);
+    }
+    if (empty($instances['commerce_discount'][$type]['commerce_compatibility_selection'])) {
+      $instance = array(
+        'field_name' => 'commerce_compatibility_selection',
+        'label' => t('Selected discounts'),
+        'entity_type' => 'commerce_discount',
+        'bundle' => $type,
+        'required' => FALSE,
+        'widget' => array(
+          'weight' => -9,
+          'type' => 'entityreference_autocomplete',
+          'module' => 'entityreference',
+        ),
+      );
+      field_create_instance($instance);
+    }
+  }
+
+  return t('Discount compatibility fields added to all discount types.');
+}
\ No newline at end of file
diff --git a/commerce_discount.module b/commerce_discount.module
index 78b1d52..04cd5a2 100644
--- a/commerce_discount.module
+++ b/commerce_discount.module
@@ -661,3 +661,50 @@ function commerce_discount_commerce_line_item_type_info() {
 function commerce_discount_line_item_title() {
   return t('Fixed amount discount');
 }
+
+/**
+ * Returns an array of discount compatibility strategies for use in a radio
+ * buttons select list.
+ */
+function commerce_discount_compatibility_strategies() {
+  return array(
+    'any' => t('This discount is compatible with any other discount.'),
+    'except' => t('This discount is compatible with any discount except the selected discounts.'),
+    'only' => t('This discount is only compatible with the selected discounts.'),
+    'none' => t('This discount is not compatible with any other discount.'),
+  );
+}
+
+/**
+ * Returns a list of discounts applied to make a particular price as determined
+ * by its price components.
+ *
+ * @param array $price
+ *   A price field value array including a data array with price components.
+ *
+ * @return array
+ */
+function commerce_discount_applied_to_price($price) {
+  $applied_discounts = array();
+
+  // Return early if the price has no components.
+  if (empty($price['data']['components'])) {
+    return array();
+  }
+
+  // Loop over the price components looking for known discount components.
+  foreach ($price['data']['components'] as $component) {
+    if (strpos($component['name'], 'discount|') === 0) {
+      // Load the discount entity represented by this component.
+      $applied_discount_name = substr($component['name'], 9);
+      $applied_discount = entity_load_single('commerce_discount', $applied_discount_name);
+
+      // Add it to the list of applied discounts keyed by ID to prevent duplicates.
+      if (!empty($applied_discount)) {
+        $applied_discounts[$applied_discount->discount_id] = $applied_discount_name;
+      }
+    }
+  }
+
+  return $applied_discounts;
+}
diff --git a/commerce_discount.rules.inc b/commerce_discount.rules.inc
index 73a9b2f..f813b22 100644
--- a/commerce_discount.rules.inc
+++ b/commerce_discount.rules.inc
@@ -12,6 +12,26 @@ function commerce_discount_rules_condition_info() {
   $inline_conditions = inline_conditions_get_info();
   $conditions = array();
 
+  $conditions['commerce_discount_compatibility_check'] = array(
+    'label' => t('Check discount compatibility'),
+    'parameter' => array(
+      'commerce_order' => array(
+        'type' => 'commerce_order',
+        'label' => t('Order'),
+        'description' => t('The order the discount would be applied to.'),
+        'wrapped' => TRUE,
+      ),
+      'commerce_discount' => array(
+        'type' => 'token',
+        'label' => t('Discount'),
+        'description' => t('A discount with a compatibility strategy that requires evaluation.'),
+        'options list' => 'commerce_discount_entity_list',
+        'wrapped' => TRUE,
+      ),
+    ),
+    'group' => t('Commerce Discount'),
+  );
+
   if (module_exists('commerce_order')) {
     $conditions['commerce_order_compare_order_amount'] = array(
       'label' => t('Order amount comparison'),
@@ -318,6 +338,98 @@ function commerce_discount_rules_event_info() {
 }
 
 /**
+ * Rules callback: executes the "Check discount compatibility" condition.
+ *
+ * @param \EntityDrupalWrapper $order_wrapper
+ *   The order the discount would be applied to.
+ * @param \EntityDrupalWrapper $discount_wrapper
+ *   The discount whose compatibility needs to be checked.
+ */
+function commerce_discount_compatibility_check(EntityDrupalWrapper $order_wrapper, $discount_name) {
+  // Ensure the discount we're loading still exists.
+  if (!$discount = entity_load_single('commerce_discount', $discount_name)) {
+    return FALSE;
+  }
+
+  // Get the strategy from the compatibility strategy field.
+  $discount_wrapper = entity_metadata_wrapper('commerce_discount', $discount);
+  $strategy = $discount_wrapper->commerce_compatibility_strategy->value();
+
+  // Determine which discounts have been applied to the order thus far.
+  $order_total = $order_wrapper->commerce_order_total->value();
+  $applied_discounts = commerce_discount_applied_to_price($order_total);
+
+  // Ensure none of them indicate they are incompatible with the current one.
+  foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {
+    // Determine the strategy of the existing discount.
+    $existing_discount = entity_load_single('commerce_discount', $applied_discount_name);
+    $existing_discount_wrapper = entity_metadata_wrapper('commerce_discount', $existing_discount);
+    $existing_strategy = $existing_discount_wrapper->commerce_compatibility_strategy->value();
+
+    // If the discount is compatible with any other discount, continue on.
+    if ($existing_strategy == 'any') {
+      continue;
+    }
+
+    // If the discount is not compatible with any other discount, return FALSE.
+    if ($existing_strategy == 'none') {
+      return FALSE;
+    }
+
+    // Get the selected discount value from the existing discount.
+    $existing_selection = $existing_discount_wrapper->commerce_compatibility_selection->raw();
+
+    // If the discount is incompatible with select discounts and the current
+    // discount was selected, return FALSE.
+    if ($existing_strategy == 'except' && in_array($discount->discount_id, $existing_selection)) {
+      return FALSE;
+    }
+
+    // If the discount is only compatible with select discounts and the current
+    // discount was not selected, return FALSE.
+    if ($existing_strategy == 'only' && !in_array($discount->discount_id, $existing_selection)) {
+      return FALSE;
+    }
+  }
+
+  // If the discount is not compatible with any other discount and we found
+  // applied discounts, return FALSE.
+  if ($strategy == 'none' && count($applied_discounts) > 0) {
+    return FALSE;
+  }
+
+  // Get the selected discount value from the disocunt being evaluated.
+  $selection = $discount_wrapper->commerce_compatibility_selection->raw();
+
+  // If the discount is not compatible with selected discounts, ensure they
+  // are not on the order.
+  if ($strategy == 'except') {
+    foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {
+      if (in_array($applied_discount_id, $selection)) {
+        return FALSE;
+      }
+    }
+  }
+
+  // If the discount is only compatible with selected discounts, ensure no other
+  // discounts are on the order.
+  if ($strategy == 'only') {
+    foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {
+      if (!in_array($applied_discount_id, $selection)) {
+        return FALSE;
+      }
+    }
+  }
+
+  // Return TRUE if nothing has disqualified compatibility yet. For example, if
+  // the discount is compatible with any other discount and no other discounts
+  // on the order specifies an incompatibility with this discount or if this
+  // discount were incompatible with other discounts but none have been applied
+  // to the order yet.
+  return TRUE;
+}
+
+/**
  * Build callback for commerce_order_compare_order_amount.
  *
  * @param EntityDrupalWrapper $wrapper
diff --git a/commerce_discount.rules_defaults.inc b/commerce_discount.rules_defaults.inc
index f4fb097..3c65081 100644
--- a/commerce_discount.rules_defaults.inc
+++ b/commerce_discount.rules_defaults.inc
@@ -46,6 +46,15 @@ function commerce_discount_default_rules_configuration() {
           )
         );
 
+      // Add the compatibility condition to all discounts. Even if the current
+      // discount is compatible with any other discount, we need to prevent it
+      // from being added if a previously applied discount indicates it is not
+      // compatible with the current one.
+      $rule->condition('commerce_discount_compatibility_check', array(
+        'commerce_order:select' => $type['entity type'] == 'commerce_order' ? 'commerce-order' : 'commerce-line-item:order',
+        'commerce_discount' => $discount->name,
+      ));
+
       // Let other modules alter the rule object, with configuration specific
       // to commerce discount. We don't invoke an alter function, as it can
       // be already achieved by implementing
diff --git a/commerce_discount.test b/commerce_discount.test
index b02c96d..35225fd 100644
--- a/commerce_discount.test
+++ b/commerce_discount.test
@@ -97,7 +97,7 @@ class CommerceDiscountTestBase extends CommerceBaseTestCase {
    * @return object
    *   The newly created commerce_discount entity.
    */
-  protected function createDiscount($discount_type, $offer_type, $amount, $name = '', $component_title = '') {
+  protected function createDiscount($discount_type, $offer_type, $amount, $name = '', $component_title = '', $sort_order = 10) {
     // Create the discount offer.
     $commerce_discount_offer = entity_create('commerce_discount_offer', array('type' => $offer_type));
     $offer_wrapper = entity_metadata_wrapper('commerce_discount_offer', $commerce_discount_offer);
@@ -128,6 +128,7 @@ class CommerceDiscountTestBase extends CommerceBaseTestCase {
       'name' => $name,
       'label' => $name,
       'type' => $discount_type,
+      'sort_order' => $sort_order,
       'component_title' => $component_title,
       'status' => TRUE,
       'export_status' => TRUE,
@@ -140,6 +141,27 @@ class CommerceDiscountTestBase extends CommerceBaseTestCase {
     return $discount_wrapper->value();
   }
 
+  /**
+   * Determines whether or not a discount has been applied to an order.
+   *
+   * @param $discount_name
+   *   The machine-name of the discount to look for.
+   * @param $order
+   *   The order object to inspect for the discount.
+   *
+   * @return bool
+   *   Boolean indicating whether or not the discount is applied to the order.
+   */
+  public function discountAppliedToOrder($discount_name, $order) {
+    // Fetch the list of discounts applied to the order based on the price
+    // components in its order total array.
+    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
+    $order_total = $order_wrapper->commerce_order_total->value();
+    $applied_discounts = commerce_discount_applied_to_price($order_total);
+
+    // Look for the given discount in the list of applied discounts.
+    return in_array($discount_name, $applied_discounts);
+  }
 }
 
 /**
@@ -153,7 +175,7 @@ class CommerceDiscountTest extends CommerceDiscountTestBase {
     return array(
       'name' => 'Discounts',
       'description' => 'Test discounts UI and functionality',
-      'group' => 'Commerce discounts',
+      'group' => 'Commerce Discount',
     );
   }
 
@@ -390,6 +412,8 @@ class CommerceDiscountTest extends CommerceDiscountTestBase {
       ]
     }
   },
+  "commerce_compatibility_strategy" : { "und" : [ { "value" : "any" } ] },
+  "commerce_compatibility_selection" : [],
   "inline_conditions" : []
 }';
 
@@ -599,4 +623,99 @@ class CommerceDiscountTest extends CommerceDiscountTestBase {
     $this->assertTrue($order_wrapper->commerce_line_items->count() == 3, 'After updating the order it still has three line items.');
   }
 
+  /**
+   * Test discount compatibility strategies.
+   *
+   * Currently implemented strategies include:
+   * - any: discount is compatible with any other discount.
+   * - except: discount is compatible with any discount except selected ones.
+   * - only: discount is only compatible with selected ones.
+   * - none: discount is not compatible with any other discount.
+   *
+   * Compatibility is checked first to ensure that discounts already on an order
+   * are not incompatible with the discount being added. It is then checked to
+   * ensure the discount being added is not incompatible with any discount that
+   * has already been added to the order.
+   */
+  public function testCommerceDiscountCompatibilityStrategies() {
+    // Create two discounts set to execute one after the other.
+    $discount_one = $this->createDiscount('order_discount', 'fixed_amount', 100, 'of1', 1);
+    $discount_one_wrapper = entity_metadata_wrapper('commerce_discount', $discount_one);
+    $discount_two = $this->createDiscount('order_discount', 'fixed_amount', 200, 'of2', 2);
+    $discount_two_wrapper = entity_metadata_wrapper('commerce_discount', $discount_two);
+
+    // Create an order and recalculate discounts.
+    $order = $this->createDummyOrder($this->store_customer->uid, array($this->product->product_id => 1), 'completed');
+
+    // Test compatibility with both discounts using the "any" strategy. Both
+    // discounts should be applied.
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && $this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Discount one and two applied when both are compatible with any discount.'));
+
+    // Test compatibility with only discount one using the "none" strategy. Only
+    // discount one should be applied.
+    $discount_one_wrapper->commerce_compatibility_strategy = 'none';
+    $discount_one_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && !$this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Only discount one applied when it is not compatible with any other discount.'));
+
+    // Test compatibility with only discount two using the "none" strategy. Only
+    // discount one should be applied.
+    $discount_one_wrapper->commerce_compatibility_strategy = 'any';
+    $discount_one_wrapper->save();
+    $discount_two_wrapper->commerce_compatibility_strategy = 'none';
+    $discount_two_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && !$this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Only discount one applied when discount two is not compatible with any other discount.'));
+
+    // Test compatibility with discount one compatible with any discount
+    // except discount two. Only discount one should be applied.
+    $discount_one_wrapper->commerce_compatibility_strategy = 'except';
+    $discount_one_wrapper->commerce_compatibility_selection = array($discount_two->discount_id);
+    $discount_one_wrapper->save();
+    $discount_two_wrapper->commerce_compatibility_strategy = 'any';
+    $discount_two_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && !$this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Only discount one applied when it is compatible with any discount except discount two.'));
+
+    // Test compatibility with discount two compatible with any discount
+    // except discount one. Only discount one should be applied.
+    $discount_one_wrapper->commerce_compatibility_strategy = 'any';
+    $discount_one_wrapper->save();
+    $discount_two_wrapper->commerce_compatibility_strategy = 'except';
+    $discount_two_wrapper->commerce_compatibility_selection = array($discount_one->discount_id);
+    $discount_two_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && !$this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Only discount one applied when it is compatible with any discount and discount two is compatible with any discount except discount one.'));
+
+    // Test compatibility with discount two compatible with only discount
+    // one. Both discounts should be applied.
+    $discount_two_wrapper->commerce_compatibility_strategy = 'only';
+    $discount_two_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && $this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Both discounts applied when discount one is compatible with any discount and discount two is compatible only with discount one.'));
+
+    // Test compatibility with discount two compatible with only discount
+    // one. Both discounts should be applied.
+    $discount_one_wrapper->commerce_compatibility_strategy = 'only';
+    $discount_one_wrapper->save();
+    $discount_two_wrapper->commerce_compatibility_strategy = 'any';
+    $discount_two_wrapper->save();
+    commerce_cart_order_refresh($order);
+
+    $properly_applied = $this->discountAppliedToOrder('of1', $order) && !$this->discountAppliedToOrder('of2', $order);
+    $this->assertTrue($properly_applied, t('Both discounts applied when discount one is only compatible with discount two and discount two is compatible with any discount.'));
+  }
 }
diff --git a/includes/commerce_discount.admin.inc b/includes/commerce_discount.admin.inc
index 72f67f6..e5887e0 100644
--- a/includes/commerce_discount.admin.inc
+++ b/includes/commerce_discount.admin.inc
@@ -240,6 +240,16 @@ function commerce_discount_form($form, &$form_state, CommerceDiscount $commerce_
     $field_form['#attributes']['class'][] = 'commerce-discount-box';
   }
 
+  // Add visibility states to the discount compatibility selection field.
+  $form['commerce_discount_fields']['commerce_compatibility_selection']['#states'] = array(
+    'visible' => array(
+      ':input[name="commerce_discount_fields[commerce_compatibility_strategy][und]"]' => array(
+        array('value' => 'except'),
+        array('value' => 'only'),
+      ),
+    ),
+  );
+
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array(
     '#type' => 'submit',
