13

I'm inexperienced with Git but I try my best to get used to it, and so far I'm just using it for projects I work on alone.

When I code there's some top-down approach naturally (as I can't know the future), and there's a reoccurring theme:

I do some work.
I find out that to get my work into something "commitable" I need to do other work.
The other work deserves it's own commit.

By something commitable I mean something that compiles or something that isn't a total mess.
And by something that deserves it's own commit I'm referring to that I learned that commits should do just one thing.

The way I resolve it is cumbersome. If the other work is in another file I make a new branch, commit there, and merge. If the work is in the same file.. ugh.. I make a local copy and reset the file to it's state in HEAD, make the needed commit and then begin to restore my work from the copy. How should I actually handle that? I don't imagine this is the way, is it? I don't assume so because it must come up somewhat often to everyone (who don't know the future too, at least). Or maybe it seems my workflow is likely to be flawed?

  • 1
    I find myself in the same situation quite often, usually when adding libraries and configurations. I just use git status to see all the changed files, and make two or more commits by using git add with specific files (instead of git add --all), and committing piece-by-piece. – Chris Cirefice Nov 14 '15 at 15:07
  • You can select parts of files with git add -p and then commit only those parts. It's a very powerful technique and I use it almost all the time. – eush77 Nov 17 '15 at 14:14
17

There are multiple ways to solve this.

If you want to do the changes for the first commit without interferring with your current changes, you might want to use git stash. This will put all your open changes away, allowing you to restore them later. Use git status to see that they are not present anymore. Now create the first commit as you are used to. Next you can use git stash pop to restore your original changes and create the second commit, doing your primary work.

Another way would be to do all required changes and then create two commits, both containing a part of your work. To do so you could use the index (also known as the staging area) provided by git. This is a special area you can use to prepare commits. Assuming you have changed multiple files, you can add each of them to the index using git add. When doing git commit only the files added to the index will be committed. git status will show you which parts of your changes will be committed and which won't. For example it will look this way after changing files a.txt, b.txt and c.txt and afterwards doing git add a.txt:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   a.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   b.txt
        modified:   c.txt

When you are doing git commit in this state, only the changes to a.txt will be added to your commit.

Additional you can review the exact changes to be committed using git diff --cached, which will show you a diff of all changes which are going to be committed.

If one file contains changes for both commits, you can also add only parts of it to the index by using "git add --patch b.txt". git will provide you an interactive mode which asks you for each change in the given file if it should be added to the index. This might get harder if you have changes in lines next to each other, which need to be splitted in the two commits, however there are ways to solve that too.

If you want to learn more about the staging area you might want to read this: http://gitready.com/beginner/2009/01/18/the-staging-area.html

You also might want to read more about interactive adding here: http://nuclearsquid.com/writings/git-add/

5

If you use a GUI for Git, like SourceTree by Atlassian, or git gui, you can commit parts of files and leave other parts uncommitted. In fact, you can commit individual lines of code.

I do this frequently when I fall down rabbit holes like you describe. This is a great way to make that sensible commit or commits as a precursor to the main commit.

You can do this from the command line, but it's kind of clumsy.

When you can commit at the Git patch level and individual lines, you don't need to create new branches, stash, commit, stash, and merge. Just keep working and don't break the flow. You've got a good thing going.

  • @MasterMastic THIS should be your accepted answer. Being able to commit just individual lines of code is a freaking godsend. – JesseTG Nov 19 '15 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.