title: git smudge/clean filter between branches
body: <p>There are many related questions involving smudge/clean filters - I have spent some hours reading them, and trying various options, but still failing. I hope I can ask in a way that I get an answer that works for me.</p>
  
  <p>Specifically, I have read the page most of these answers link back to:</p>
  
  <ul>
  <li><a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes" rel="noreferrer">Customizing Git - Git Attributes</a></li>
  </ul>
  
  <hr>
  
  <h2>tl;dr</h2>
  
  <p>Its a detailed question, but the summary is:</p>
  
  <ul>
  <li>Can I store <code>DEBUG = false</code> in a file on one branch, and <code>DEBUG = true</code> in another branch, using smudge/clean filters to manage that file? And how?</li>
  </ul>
  
  <hr>
  
  <h2>Background</h2>
  
  <p>I have various remote repos hosted at bitbucket. I am using SourceTree on Win8, to clone the remote repos to my laptop. I create different branches for development, features, releases etc (following <a href="http://nvie.com/posts/a-successful-git-branching-model/" rel="noreferrer">A successful Git branching model</a> for better or worse).</p>
  
  <p>I have an Android java class called <code>Dbug.java</code> that contains a boolean which turns on/off various debug logging, mocking etc features in my code.</p>
  
  <pre><code>public static final boolean DEBUG = false;
  </code></pre>
  
  <p>I would like this value to be <code>false</code> on my "production" (master) branch, and to be <code>true</code> on my feature branches.</p>
  
  <ul>
  <li><strong>Is this possible using filters, or have I already misunderstood the use case?</strong></li>
  <li>I am unsure if filters work like this between 2 branches of the same locally hosted repo, or if the filters only work between 2 repos.</li>
  </ul>
  
  <hr>
  
  <h2>Creating the filters</h2>
  
  <p>Working locally, I checked out the production branch. I created a test file called <code>debug_flag.txt</code> with the following contents:</p>
  
  <pre><code>// false on production branch
  // true on other branches
  DEBUG = false;
  </code></pre>
  
  <p>I created a file in the root of my local repo called <code>.gitattributes</code> and added the filter reference to it:</p>
  
  <pre><code>debug_flag.txt filter=debug_on_off
  </code></pre>
  
  <p>I updated the <code>.git/config</code> file with the filter definition:</p>
  
  <pre><code>[filter "debug_on_off"]
      clean = sed -e 's/DEBUG = true/DEBUG = false/'
      smudge = sed -s 's/DEBUG = false/DEBUG = true/'
  </code></pre>
  
  <ul>
  <li>In my understanding, this should ensure that my file always has a
  false value in production, but will have a true value when I branch from
  production. </li>
  <li><strong>Is this a correct understanding?</strong></li>
  </ul>
  
  <hr>
  
  <h2>Testing the filters</h2>
  
  <p>I created a new branch <code>test</code> using:</p>
  
  <pre><code>git checkout -b test
  </code></pre>
  
  <p>I checked the contents of my file:</p>
  
  <pre><code>$ cat debug_flag.txt
  
  // false on production branch
  // true on other branches
  DEBUG = false;
  </code></pre>
  
  <ul>
  <li><strong>I expected to see the value <code>true</code> in the file</strong></li>
  <li>Shouldn't the "smudge" filter have run when I checked out the file?</li>
  </ul>
  
  <p>I added a new line to the file, and committed. I then switched back to the production branch, and this is where things get <strong>weird</strong>.</p>
  
  <p>If I look at the file in SourceTree, there are no changes on this branch since it was created. That is what I would expect, since the only change was made on a different branch.</p>
  
  <p>If I look at the file in the terminal, or Notepad++, I see my value has changed:</p>
  
  <pre><code>$ cat debug_flag.txt
  
  // false on production branch
  // true on other branches
  DEBUG = true;
  </code></pre>
  
  <p>I have not yet merged the change across from the test branch, I have not made a commit on the production branch, yet <strong>the file has changed</strong>.</p>
  
  <ul>
  <li>it looks like the smudge filter was run on the file within this branch, but not across branches.</li>
  </ul>
  
  <hr>
  
  <p>I'm missing a vital piece of the puzzle, and hopefully it is something simple that can be spotted by someone with experience doing this.</p>
  
  <p>My bet is this is a simple misunderstanding of the concept.</p>
  
  <p>Pls prompt for any missing info...</p>
  
  <hr>
  
  <h2>Update based on VonC's reply</h2>
  
  <p>Setting up the basic filters worked quite well. Defined the filter in the <code>config</code> file as:</p>
  
  <pre><code>[filter "debug_on_off"]
      clean = sed -e 's/DEBUG = true/DEBUG = false/'
      smudge = sed -s 's/DEBUG = false/DEBUG = true/'
  </code></pre>
  
  <p>Creating a new branch fixes false -> true, merging back changes true -> false.</p>
  
  <p>Confining the change to just the production (master) branch required custom scripts that were aware of the branch they are being run from. So the <code>config</code> file became:</p>
  
  <pre><code>[filter "debug_on_off"]
      clean = ./scripts/master_clean.sh
      smudge = ./scripts/master_smudge.sh
  </code></pre>
  
  <p>master_clean.sh:</p>
  
  <pre><code>#!/bin/sh
  branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
  if [ "master" = "$branch" ]; then
      sed -e s/DEBUG = true/DEBUG = false/ $1
  else
      cat $1
  fi
  </code></pre>
  
  <p>master_smudge.sh:</p>
  
  <pre><code>#!/bin/sh
  branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
  if [ "master" = "$branch" ]; then
      sed -e s/DEBUG = false/DEBUG = true/ $1
  else
      cat $1
  fi
  </code></pre>
  
  <p>At this point, I am running into inconsistencies between what SourceTree is seeing, and what is being shown in Notepad++ for the contents of the debug file. SourceTree is showing the changes, but Notepad++ is not.</p>
  
  <p>I am accepting <a href="https://stackoverflow.com/a/22910075/383414">VonC's answer</a>, since it answers the basic question I posed. </p>
  
  <p>However, I will likely be implementing the <a href="https://stackoverflow.com/a/22914145/383414">solution I wrote</a>, since it solves the underlying problem that I am trying to solve, in an easier way (for me): retaining a different config file on separate branches.</p>