25

There are multiple questions on Stack Overflow addressing the problem of staging and committing only parts from files. However, I can't make it work.

Let's say we want to implement a dummy math class in php (the language doesn't matter) with some basic methods like: add, subtract, multiply and divide.

Let's start with the class definition:

<?php
    class Math {
    }
?>

Now:

$ git add math.php
$ git commit -m "Create Math class."

In the next step we implement both add and subtract four methods:

<?php
    class Math {
        public function add($a, $b) {
            return $a + $b;
        }

        public function subtract($a, $b) {
            return $a - $b;
        }
    }
?>

But now we want to commit the implementation of the add and the subtract methods in separate commits.

Is this possible?

What I tried

$ git add -p

The following appears:

enter image description here

I would love to split the hunk into smaller hunks, so I press s, and the following appears:

enter image description here

It seems that git didn't split it into smaller hunks.

Let's try now to manually edit the current hunk. So I press: e.

My default text editor (sublime text) opens up, and here I can edit the hunk:

enter image description here

I try to simply delete line 8,9,10,11 - because I want to stage only the add function. I save, close the editor, but git says:

Your edited hunk does not apply. Edit again (saying "no" discards!) [y/n]?

I'm really new to git add -p and interactive staging, so maybe it's something I do wrong, or simply it's not possible what I want, and really hope some more experienced git users have some instructions maybe also a solution for me.

Thank you!

Community
  • 1
  • 1
Tamás Pap
  • 17,777
  • 15
  • 70
  • 102
  • 1
    Are you trying to learn the "git way" of doing it? Personally, I don't bother with such details. I'd just remove one function, commit that, add it back in, and commit that. – TheBuzzSaw Apr 21 '13 at 18:26
  • Yeah, this is exactly what I've done in my last project. Maybe this is the easier way. However, I would love to do it in git, then decide which way to choose. – Tamás Pap Apr 21 '13 at 18:27
  • possible duplicate of [Commit only part of a file in Git](http://stackoverflow.com/questions/1085162/commit-only-part-of-a-file-in-git) – 7ochem Apr 03 '15 at 08:31

2 Answers2

17

You are doing exactly what I've done in the past, and I even recreated your entire experiment on a UNIX machine and it worked just as expected.

I suspect your editor is changing the line endings in the diff hunk when it saves.

Ben Jackson
  • 90,079
  • 9
  • 98
  • 150
  • 1
    I'm back. I set up all my editor to use unix line endings, and everything works as expected. – Tamás Pap Apr 22 '13 at 20:25
  • Beyond line _endings_, Sublime's `trim_trailing_white_space_on_save` setting will also break diffs if the hunk in question has trailing whitespace. It is off by default, but maybe the asker turned it on. To turn it off for diffs specifically: When the diff popped open for editing, choose **Preferences** -> **Settings - Syntax Specific** from the menubar and save `{ "trim_trailing_white_space_on_save": false, }` into the opening `Diff.sublime-settings` file. – nh2 Mar 06 '20 at 22:31
14

This doesn’t feel like the absolute “git way” to do it this since git loves the command line, but here’s what i do:

Git comes bundled with git gui – you can start it by running just that command. There you can select your unstaged file, mark the lines you want to commit and click “stages lines for commit”. If you want it to behave more like a command-line tool, you can run git gui citool, which has the effect that the ui will close when you commit.

Partial staging with git gui

Note that this tool is properly integrated with git. You don’t need to make your commit in this ui. You can just stage the relevant lines, close it, maybe do some more git add and then commit via the command line.

In general I love the git comand line interface and even though I am not necessarily a shell fan, I just got to love it after a while. I tried multiple GUIs and threw them all away because they can’t compete with the git command line interface. But for git add -p I would definitely say that that is a task for a GUI. Doing partial commits is just way easier with git gui. Same goes for complex history browsing. gitk (also shipped with git) does a way better job there than git log --graph -p (as long as you really need to understand the tree and don’t quite now about the state of the history).

Note: But you still seem to be doing everything right – I tried what you did and have to agree with Ben Jackson. That should definitely work. Your editor must be screwing something up.

Final Note: You seem to be using the git command line with the standard windows cmd terminal. I strongly recommend switching to mintty. Download the msys version, put it in your Program Files\Git\bin directory and run it (create a shortcut) with mintty -. This will get you the same shell, but with better everything (especially better resizing and copy&paste).

Chronial
  • 66,706
  • 14
  • 93
  • 99
  • `git add -p` is a traditional git way. I've always used it and have never had any issues. It might be just the editor which does not seem to add the correct line endings which git is expecting. BTW to use `git gui` on Windows you should be using either cygwin or msys. – Tuxdude Apr 21 '13 at 23:49
  • I know that `git add -p` works and should work for what OP is trying to achieve. My point is that it’s easier to stage parts of a file when you can properly scroll through it and stage single lines without having to switch to an editor. And if you use git on Windows, it is always with cygwin or msys – git can not run natively on windows at all due to its shell scripts. – Chronial Apr 22 '13 at 00:52
  • Thank you for your detailed comment. I also tried git gui, but the same error appeared. The line ending were the key to the solution as Ben Jackson and you pointed out. Now also git gui works as expected. – Tamás Pap Apr 22 '13 at 20:28