23

Often while working on a branch I need to introduce some "temporary" changes (such as additional debugging info, or a change which lets me better observe the thing i'm actually working on).

About these "temporary" changes:

  • I want them in my working copy of my branch, because they help me to work on the actual change,
  • I don't want them committed to the branch, because the branch is going to be merged into master some time and they're not production code.

Currently I just keep them as unstaged and I skip them manually when staging every commit. However I can't stay with this solution because:

  • All the time I have to remember which files I need to skip,
  • Someday I'm going to end up with 2 changes in one file, one being temporary, one to be committed, and it's going to be really troublesome.

How should I deal with it?


gitignore is obviously out of the question because I don't want to ignore the whole files and I'm still interested in changes from other committers (I need to rebase the branch to master from time to time).

Kos
  • 70,399
  • 25
  • 169
  • 233
  • It looks like an interesting idea to try extending ignoring to hunk granularity. Might even be worth trying to ask on the git mailing list (you don't have to subscribe to post and as it's rather high volume, you probably don't want to). – Jan Hudec Aug 22 '11 at 13:21
  • 1
    Actually gitignore is not out of question, because if the file is versioned, you *will* get the committed version of it. It's only add that will ignore it. It does not however handle the case when you want to ignore only some changes to a particular file and sooner or later you do want to. – Jan Hudec Aug 22 '11 at 13:23
  • I've added an idea of my own, looks OK to me but I'd appreciate if someone more experienced could have a look if there are no problems with it. – Kos Aug 22 '11 at 13:34
  • Was about to ask the same question. .hunkignore would be kind of cool. The rebase solutions seem effective, however. – Koobz Nov 03 '12 at 03:23

10 Answers10

14

I typically deal with this by using:

git add -p

... to stage changes hunk-by-hunk. Then you just have to make sure to press n for your debugging changes.


If I have more involved changes of this type, I'll create a branch called something like local-changes with a commit at its tip that introduces the debugging code. After creating a few more commits, I'd then use:

git rebase -i master

... to reorder them so that the commit with the local changes is at the tip again. Then to update master and return to the local changes branch, you can do:

git checkout master
git merge local-changes^
git checkout local-changes
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
6

Try git update-index --assume-unchanged <file>. This way git will not add the file to the index when using git add or git commit -a.

EDIT: This doesn't allow you to deal with the case of having one file with both temporary and permanent changes.

Chaitanya Gupta
  • 4,043
  • 2
  • 31
  • 41
  • It's probably worth pointing out the consequences of using `--assume-unchanged` can also be really confusing :) – Mark Longair Aug 22 '11 at 13:24
  • 1
    @Mark I have never been confused when using `--assume-unchanged`. Can you elaborate? The only difficulty I have faced once or twice is finding out which files have this flag set. – Chaitanya Gupta Aug 22 '11 at 18:04
  • 1
    This is great. From the docs: *"Git will fail (gracefully) in case it needs to modify this file in the index e.g. when merging in a commit;"*. Would be nice if it unset the assume-unchanged bit when that happened, but I don't think it does. Also, it'd be nice if `git status` reminded you of `assume-unchanged` files. – naught101 Jun 21 '12 at 06:10
  • I use an alias `ignored = !git ls-files -v | grep "^[[:lower:]]"` to check for files marked this way. – Kos Jan 30 '17 at 09:39
5

Here's a way to deal with this that, once set up, only requires you to remember one step to set it up, and one step before each push.

The setup:

git branch tempChanges  [branch for temporary changes]
  [create your temporary changes]
git add -A
git commit

Note the sha for that commit. Then switch to your working branch, and:

git cherry-pick shaOfTempChangesCommit

Now you have the changes on your working branch. Do your work and make commits. Then, before you push:

git rebase -i

You'll see something like this:

pick bfd4d2e This first commit is your temporary changes.
pick 186a99d Some stuff done on the working branch.
pick ec871c6 More stuff done on the working branch.
(etc.)

Delete the line with your temporary changes. Then save and exit. Your history will be rewritten to exclude the temporary changes. (The changes will still exist in the tempChanges branch.) Once that's done, do any testing you need to and then git push.

When you're ready to work again, you can pull the temporary changes back onto your current working branch (or a new working branch):

git cherry-pick shaOfTempChangesCommit

So, in sum, all you have to remember in this method is

  • after you create a working branch

    git cherry-pick shaOfTempChangesCommit

  • after you're done working and ready to push

    git rebase -i [to remove the temporary changes before you push]

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
4

You can use

git stash

to save it into a temporary spaces. After doing your merge, you can use

git stash pop

to load back your temporary changes into your working-directory.

TheOneTeam
  • 25,806
  • 45
  • 116
  • 158
  • this doesn't discriminate between useful global changes and local-only changes, as the OP requested.. – naught101 Jun 21 '12 at 06:00
  • I'd love stash if it was branch-specific. As is, it is kind of a pita to keep track of all the different stashes – eric May 23 '23 at 18:45
1

What about writing a simple shell script that will patch and undo your debug changes on request (and then make it as a git alias).

E.g.

git apply-my-debug
...
do coding
...
git remove-my-debug
git add .
git commit -m "Don't worry about debug changes"
random
  • 11
  • 1
1

To avoid cluttering up your staging area as you're creating a feature, commit your debug changes with a bright blinking warning that they should not make it into the final merge:

#warning - DEBUG ONLY - DO NOT MERGE

print(debugInfo)

#warning - DEBUG ONLY - DO NOT MERGE

When you're ready to merge the branch, if you've forgotten about them, these changes will be caught by you or someone else in the code review of your pull request.

You'll then have different ways to remove the debug commits:

  1. revert the specific debug commits. This will retain their history in the branch.

  2. cherry-pick the good commits. This will remove the debug commits entirely.

  3. Something more complicated such as rebase -interactive to remove the commits in-place.

pkamb
  • 33,281
  • 23
  • 160
  • 191
1

I've found a clean solution to this problem: (pardon my ascii-art). It requires an additional branch for the topic branch. (this has flaws and is being disputed/corrected, see comments)

The work looks like this initially:

master
     \
      \
     commit1  ---- commit2 ---- "branch"

Work is done on "branch".

To introduce some temporary changes:

  • create branch "branch-temp" from "master"
  • commit the temporary changes there
  • rebase "branch" from "master" onto "branch-temp"

The repo now looks like:

master
     \
      \
     "branch-temp" ----- commit1 ---- commit2 ---- "branch"

Work is now happily continued on branch and the temporary changes are not visible in the status.

To change or extend the temporary changes:

  • checkout branch-temp
  • commit --amend the temporary changes there - this is wrong, since it makes "branch-temp" diverge

To merge the changes from branch to master:

This is just a bit more tricky. We want to merge in all changes, except the changes introduced by "branch-temp". My idea is:

  • run a normal merge from "branch" onto "master"
    (we now have a merge, but with some unnecessary temporary changes - let's remove them)
  • git revert --no-commit branch-temp
  • git commit --amend
    (these two steps should modify the merge commit, so that it no longer contains the changes from branch-temp)
Kos
  • 70,399
  • 25
  • 169
  • 233
  • I would instead rebase onto master, using interactive rebase and just remove the not-to-be-used commits (marked with [test] or something in their subjects). That would also avoid the need for "branch-temp" and result in linear history. – Jan Hudec Aug 22 '11 at 13:43
  • The `git checkout branch-temp` + `git commit --amend` will not work as presented, because after that `branch-temp` will have the new version, but `branch` will still have the old version of the commit. And I am not sure plain `git rebase --onto branch-temp` would fix that up. It's easier to `git rebase -i` and edit the commit that way, but that will leave the `branch-temp` behind (that's what I'd use and drop the commit using rebase instead or merge+revert). – Jan Hudec Aug 22 '11 at 13:46
  • Yes, you're right- I checked the doc and commit --amend creates a new commit and updates the current branch, while I thought it modifies the commit on HEAD in-place. – Kos Aug 22 '11 at 14:17
  • @Jan, if instead of amending I'd just simply add a new commit to `branch-temp` and then rebase `branch` to new head of `branch-temp`, would that be correct? Also the way to merge would need to be modified... I'd be most content with a way which wouldn't require me to actually modify the topic branch, in case I need to resume the work on it. – Kos Aug 22 '11 at 14:25
  • Yes, it will be correct. Ad resuming though, that's useless. When you merge the branch to master with reverting the temporary commits than if you later merge from master to the branch, you will also merge the reversal, so you won't have the temporary changes anyway. – Jan Hudec Aug 23 '11 at 07:11
1

I usually put all my debug code in its own commit, then before I do the merge, I revert that commit. I've used some variation of most of the other answers at times, but I like this one for its simplicity and the fact that it preserves my development history. Yes, I don't want my debug code in the final product, hence the revert, but if testing finds an issue I want to be able to reinstate that debug code for further work.

Karl Bielefeldt
  • 47,314
  • 10
  • 60
  • 94
0

GIT's stash functionalities provides exactly what you're asking for. At least for the "keeping" part. Making the good/bad-selection when committing cannot be avoided like this.

Patrick B.
  • 11,773
  • 8
  • 58
  • 101
0

I tend to keep uncommitted changes like that. I simply always use git add -i or git add -p to stage changes (unless I am sure I want all changes the tree has). That way I review all the changes I do want committed and easily skip temporary ones. It also helps to stage changes you know you'll want committed early and keep them staged or even commit them and than add more changes with git commit --amend.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172