How can I add a cancel button to the content add form for a single content type? I have several content types on a site and most of them are user-editable but not user-creatable.  However, one content type, Image, allows users to upload a picture.  Sometimes, however, users upload the wrong picture and they panic because they don't want that picture to be submitted to the site.

Of course they could always hit the browser's back button, but I'd like to add a Cancel button for additional assurance.

I found this thread that gives various solutions for adding cancel buttons on Drupal.org as well as this feature request for adding a cancel button to D8.  However, there are several different general approaches and I don't know how to limit one to a given content type (in this case, my_image).
I would use the following code.

function mymodule_form_my_image_node_form_alter(&amp;$form, &amp;$form_state) {
  // If the node is being created, redirect the users to the page where
  // they can choose the content type for a new node; otherwise, redirect
  // them to the page showing the node.
  $destination = (!isset($node-&gt;nid) || isset($node-&gt;is_new)) ? 'node/add' : "node/{$node-&gt;nid}";

  $form['actions']['cancel'] = array(
    '#markup' =&gt; l(t('Cancel'), $destination),
    '#weight' =&gt; 20,
  );
}  


Notes


markup is the default form element type; there is no need to use #type = 'markup'.
In the node edit form, all the buttons are inside $form['actions']. The weights used from the buttons that form is using are 5 (Save), 10 (Preview), and 15 (Delete). I used 20 to show the link after those buttons, but you can change its weight to show it in a different position.

// Add the buttons.
$form['actions'] = array('#type' =&gt; 'actions');
$form['actions']['submit'] = array(
  '#type' =&gt; 'submit', 
  '#access' =&gt; variable_get('node_preview_' . $node-&gt;type, DRUPAL_OPTIONAL) != DRUPAL_REQUIRED || (!form_get_errors() &amp;&amp; isset($form_state['node_preview'])), 
  '#value' =&gt; t('Save'), 
  '#weight' =&gt; 5, 
  '#submit' =&gt; array('node_form_submit'),
);
$form['actions']['preview'] = array(
  '#access' =&gt; variable_get('node_preview_' . $node-&gt;type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED, 
  '#type' =&gt; 'submit', 
  '#value' =&gt; t('Preview'), 
  '#weight' =&gt; 10, 
  '#submit' =&gt; array('node_form_build_preview'),
);
if (!empty($node-&gt;nid) &amp;&amp; node_access('delete', $node)) {
  $form['actions']['delete'] = array(
    '#type' =&gt; 'submit', 
    '#value' =&gt; t('Delete'), 
    '#weight' =&gt; 15, 
    '#submit' =&gt; array('node_form_delete_submit'),
  );
}

There isn't the need to use arg() to understand if the form is for editing an existing node, or for creating a new one. I checked !isset($node-&gt;nid) || isset($node-&gt;is_new) is TRUE, to verify the node is being created. Drupal seems to simply check empty($node-&gt;nid), even though node_object_prepare() uses !isset($node-&gt;nid) || isset($node-&gt;is_new).
If $_GET['destination'] is set, the link added with l() will point to that path.