50

As interesting and useful as the answer to How to setup a git driver to ignore a folder on merge was, it did not answer the original question which still has me stumped.

Unlike the question linked to above, I have two branches with the same set of directories and for merging one into the other I need git to ignore one directory completely.

I tried it with my own merge driver as described in How do I tell git to always select my local version for conflicted merges on a specific file? but the problem with this approach is that this driver is only invoked when there is an actual conflicting file in these two branches. Whenever the changes of a file are only on one branch, git merges them without calling my merge driver.

This leads to changes in files in the directory that I do not want. Any idea how I could make git ignore each and every file in that directory all the time - whether it was touched or not?

Community
  • 1
  • 1
Sebastian Thiebes
  • 503
  • 1
  • 4
  • 8
  • I've been looking into git lately, and this seems to be one of the problems that might prevent us from using it, you can't selectively merge things. – user606723 Jan 16 '13 at 23:02
  • the `git filter-branch` command may be what your looking for. It allows you to do a merge while filtering what gets merged. http://git-scm.com/docs/git-filter-branch – David Culp Jan 16 '13 at 23:25
  • Thanks fpr the answer, yet I do not understand how I could apply `filter-branch` in this specific case without doing a lot of manual work for every merge. – Sebastian Thiebes Jan 17 '13 at 08:38

2 Answers2

86

I don't actually use Git, but I think this would work for your case:

Use something like what's specified here: https://gist.github.com/564416

git checkout master    
git merge --no-commit --no-ff development
git reset -- /path/to/folder # revert updates from path
git commit

Again, I don't use git, I am just deferring to how I think things work based on my experience with TryGit.

  1. checkout master
  2. merge, but don't commit, no fast forward.
  3. merges are now staged, so reset that entire directory tree
  4. commit
demisx
  • 7,217
  • 4
  • 45
  • 43
user606723
  • 4,918
  • 2
  • 27
  • 34
  • 1
    I think you should also give this answer in [How to setup a git driver to ignore a folder on merge](http://stackoverflow.com/questions/3111515/how-to-setup-a-git-driver-to-ignore-a-folder-on-merge). Maybe also consider not showing the checkout step? It's irrelevant, and I think it detracts from the simplicity of the solution. – jthill Jan 17 '13 at 04:07
  • 1
    If my edit doesn't take, the reset should be `git reset -- path/to/folder` – jthill Jan 17 '13 at 04:13
  • This looks promising, thanks @jthill! I have trouble understanding the state the branch is in after I reset: `git status` shows me all the changes in `path/to/folder` as not staged for commit and in addition I now have many untracked files in there as well. How can I proceed with these to revert them to the state before the merge? – Sebastian Thiebes Jan 17 '13 at 08:33
  • So, I can revert the files not staged for commit to their pre-merge state via `git checkout -- path/to/folder`. That leaves all these untracked files - how did they come about and how to revert them as well? – Sebastian Thiebes Jan 17 '13 at 09:32
  • Now that is clear to me as well - all these untracked files are the ones that were newly created as they came from the other branch and the `reset` does not delete them completely but just removes them from tracking. – Sebastian Thiebes Jan 17 '13 at 09:50
  • 1
    It seems there is still a problem: I tried removing the untracked files - that would have been added in the directory as a result of the merge und there are some that persist. However, these were never present on the original branch, so it seems that `reset` and `checkout` did not have the desired effect completely. – Sebastian Thiebes Jan 17 '13 at 10:22
  • @SebastianThiebes If you deleted the files and git's not tracking them I can't think where they'd come from. If your worktree was clean, you can delete all the untracked files with `git clean -f`, add `-x` to clean the ignored ones as well. – jthill Jan 17 '13 at 15:17
  • OK, this does do the correct thing - in a simple example I just tried. In the case of my real repo, the subdirectory in question is in a strange state after `reset`, `checkout` and `clean` because `clean` would not delete some sub-subdirectories because there were still files in them. Files that are neither tracked nor cleaned nor even mentioned as not removed by `clean`. I will examine this and perhaps formulate a new question for this. – Sebastian Thiebes Jan 18 '13 at 08:30
  • 1
    shouldn't the reset be a --hard reset? – user338519 Apr 23 '14 at 18:42
  • 2
    The main problem with that if you decide to merge later that folder it won't get merged, as git thinks that it has already merge that. So it is a workaround that will break your workflow – Codingday Jan 12 '16 at 16:13
0

Let's say I'm on branch staging want to merge dev and ignore changes in /build folder:

git checkout staging
# go to staging branch

git checkout dev .
# this checkout dev file changes into staging

git reset HEAD build
# this remove added file in build folder

git clean -f
# this drops untracked files we just reseted

git checkout -- .
# this drops changed files we just rested

git status
# check is everything ok

git commit -am 'merge dev into branch'
# create a commit

git merge -s ours dev
# this create a fake merge to trick Git into thinking that a branch is already merged when doing a merge later on.

this solution is not perfect because it will merge all commits into one. which means cherry-pick some commits may not suitable.

but it's able to avoid lots of commit in build folder caused by rename/new/delete that need to clean up.

Gavin Kwok
  • 98
  • 6