16

This is similar to this question on merging, except that I am attempting to rebase branch A onto branch B, instead of merging branch B into branch A.

It is possible to achieve a similar effect in branch A using a combination of git checkout and git commit on individual files, but that does not have the same effect on the history as a rebase.

Is it possible to rebase only specific files so that all future rebases will not need to touch these files, without rebasing the history of all files?

Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329

5 Answers5

10

Sort of. You might do interactive rebase, and when presented with the rebase script in your text editor, change all the actions from "pick" to "edit" then save and quit. Rebasing will now begin and it will stop after each commit applied making it possible for you to:

  1. Delete the changes in the files you're not interested in.

    This is doable by something like

    git reset <reference_commit> -- pathname
    

    where the <reference_commit> is the name of a commit which contains the files you don't want the rebasing to modify.

  2. Apply these changes by running git commit --amend -C HEAD.

  3. Run git rebase --continue.
  4. Rinse, repeat.

Any time git rebase applies the next commit being rebased you might be presented with a conflict instead of just a chance to edit the already recorded commit. This does not differ much from the normal editing — you just need to pay more attention to the current status of the index.

In any case, what you want to do, smells pretty strange to me: rebasing, normally, is "forward-porting your local changes on top of the updated base (upstream code)" which means if your changes can't work with updated upstream (and why else you'd want to keep some files from updating?) there's no sense in rebasing—simply because you'll not be rebasing, you'll be doing something else, and this might bite you later.

kostix
  • 51,517
  • 14
  • 93
  • 176
1

You can revert a file to what is last committed with git checkout [file path]. For example:

git checkout /views/index.html
cokeman19
  • 2,405
  • 1
  • 25
  • 40
0

Git really works on a whole-repository basis, not a per-file basis, so you will find no easy way in git to do this

user128364
  • 4,533
  • 3
  • 20
  • 12
  • This is a really good answer, +1, but needs improvement. You need to state what the drawbacks are for the "revert" and "checkout' options. – Jonathan Ben-Avraham Jun 13 '21 at 08:02
  • I managed to do it by using a mix of git and PowerShell, for example the following will get the files that have been added or updated between two commits, excluding files with specified file extensions, and check them out in the current branch... foreach ($changedFile in (git --no-pager diff --name-only --diff-filter=AMCR sha1 sha2 | ? { ($_ -notlike '*.sln' -and $_ -notlike '*.yml')})) { git checkout develop $changedFile } – ZenoArrow Oct 18 '21 at 19:51
0

Try git revert. Search for the specific commit hash that introduced the unwanted change and use that as the argument. git revert then will generate a patch that undoes those exact changes.

Note, this means that your commits are small in volume (not modifying lots of files), as they should be. As such, the updates in the repository to other files will remain unaffected and only those dealing with that specific commit will be changed.

jhill515
  • 894
  • 8
  • 26
0

I believe what you're looking for is git checkout --patch BRANCH_NAME FILE_PATH

Note that if you omit the --patch you will simply overwrite the file.

Er...
  • 526
  • 4
  • 10