How to permanently prevent specific part of a file from being committed in git?

There might be a possiblity with filters. But this needs to be explored more.

Starting point: Implement the smudge / clean for this filter:

git config --global filter.versionUpdate.smudge 'sed "s/<version>14.5.0<\/version>/<version>14.5.FEATURE-15<\/version>/"'
git config --global filter.versionUpdate.clean 'sed "s/<version>FEATURE-15<\/version>/<version>14.5.0<\/version>/"'

In this way, the file is always the same when comparing, since the filter is applied.

Problem: It still needs investigation on how to find the filtered files back. This is not so evident in the working directory.

Smudge clean filter


It might be easier to solve your problem outside of git. You can define a property with a default value in pom.xml, which everyone uses. And for your exclusive setup you simply override the property in your ${user.home}/.m2/settings.xml or on maven command-line using -Dproperty=value. Or similarly, you can create another profile and activate it based on an environment variable that you export in your, say, ~/.bashrc.

For a git solution, I was accomplishing what you want with some discipline in following the workflow properly:

  1. Make your setup-specific changes to pom.xml (or other files).
  2. Commit the changes into git (locally only). State in the commit title/message that the changes are for local use only, like "LOCAL ONLY. DO NOT DCOMMIT: rest of the title".
  3. Pull changes from svn, make local git commits, etc.
  4. Once it's time to dcommit your changes back to svn, do
    1. git svn rebase to pull new commits from SVN, resolve conflicts.
    2. git rebase -i svn/trunk (or whatever is your svn remote branch) (this will start interactive rebase of all your local changes on top of SVN)
    3. In the interactive rebase todo editor, move your local-only commit to the bottom.
    4. Save the todo and exit the rebase todo editor.
    5. Resolve any conflicts (should be none unless you touched the same part of your pom.xml (or other local-only file) in other local commits).
  5. Run git svn dcommit --dry-run @~1 (or git svn dcommit --dry-run HEAD~1 in older git) to see what's going to be pushed to SVN repository; make sure your local-only commits are not in the list.
  6. Run git svn dcommit @~1 (or git svn dcommit HEAD~1) to finally push your changes to SVN repository.
  7. git svn rebase to pull new commits from SVN.

It may sounds complicated, but it's pretty simple once you get used to it. Basically, you have one (or more) local commits, which you never push to SVN. I haven't had a wrongly pushed commit in more than a year using this workflow with multiple commits and repositories. It's quite useful for having some local debug-only changes, for example (although it's better to introduce an environment variable or some settings file for this).

Furthermore, this can be enhanced with a pre-dcommit hook in git, which would make sure that local-only changes are not being dcommit'ed. Unfortunately, I don't see a standard git-svn hook for this, but one could use git-svn-hooks to implement those.


EDIT: What you are asking is impossible, I didn't see the "partial" part. I know you can commit only part of files, but you cannot ignore some part of file. You will need to use the update-index trick to avoid having it in the "status" and you will need to stash that file every time you will rebase/merge from the remote, and then unstash your modification and ignore your modification with update-index. I don't know if you can create a git alias for a sequence of git commands so with one command you could do all those 3 commands to avoid the hassle

use a .gitignore file, and don't push it to the remote repo too: Ignore the .gitignore file itself

in your .gitignore, you should have

 .gitignore
 path/to/pom.xml

a .gitignore file can be at the root of the working tree, or in any subdirectory you want/need