13

I often encounter the following scenario:

modified:   assembly/main.debug.s
modified:   ../src/cd/Config.java
modified:   ../src/cd/memoization/cfg/SubgraphFinder.java
modified:   ../src/cd/memoization/cfg/SubgraphMap.java
modified:   ../src/cd/profiler/Profile.java
modified:   ../test/cd/test/TestSamplePrograms.java
modified:   ../../notes/20150521.txt

Here I have a bunch of files and I want to include them in different commits. What I do so far is to do a bunch of git add <pathspec> followed by a respective git commit. The <pathspec> is what annoys me. Is there something like the following?

1 modified:   assembly/main.debug.s
2 modified:   ../src/cd/Config.java
3 modified:   ../src/cd/memoization/cfg/SubgraphFinder.java
4 modified:   ../src/cd/memoization/cfg/SubgraphMap.java
5 modified:   ../src/cd/profiler/Profile.java
6 modified:   ../test/cd/test/TestSamplePrograms.java
7 modified:   ../../notes/20150521.txt

git magic 2,3,5 -m "My super simple commit"

Nick Volynkin
  • 14,023
  • 6
  • 43
  • 67
ben
  • 5,671
  • 4
  • 27
  • 55
  • "I have a bunch of files and I want to include them in different commits". ok so what are you actually trying to do that requires that? All files are included in any git repo. If you change a file the change exists on a branch somewhere, even if just master. What are you trying to achieve (big picture) that is leading you to this question? – Michael Durrant May 23 '15 at 11:04
  • So, you want something like `git commit -a -m "...."`, but it should be selective (not all modified files as it is done with `-a`)? That would indeed sound like an interesting feature to save some time – Slizzered May 23 '15 at 11:05
  • It sounds like you're looking for an interface for git, something like Magit, perhaps? https://www.masteringemacs.org/article/introduction-magit-emacs-mode-git – asjo May 23 '15 at 11:07
  • I would create a .gitignore file to either excluding all paths you don't want to add or exclude all files and specify the once to be included. Then use `git add . --all` followed by git commit. Here is a link that might help: http://stackoverflow.com/questions/30322696/git-missing-some-files/30322823#30322823 – Peter Paul Kiefer May 23 '15 at 11:11
  • 1
    @MichaelDurrant The big picture is very simple. Just imagine you modify multiple files in a git repo and the changes you made semantically belong in different commits. #Slizzered This is exactly what I want to do. Ideally not by specifying paths individually but by a git status showing some kind of enumeration as in my question to allow easier selection of files. #Peter Paul Kiefer This sounds tedious to me. – ben May 23 '15 at 11:17
  • Ah, sorry I've overseen your requirement of adding files in different commits. I think then you have to specify the paths in git add separated by spces and with wildcard notation if you want to add all files in a directory `git add dir/**` – Peter Paul Kiefer May 23 '15 at 11:18
  • Have you considered using a git client? Like [tig](http://blogs.atlassian.com/2013/05/git-tig/) – bdecaf May 23 '15 at 11:32
  • @bdecaf If you are talking about GUI clients then yes. I'm looking for something without GUI. – ben May 23 '15 at 11:39
  • @ben - just for clarification - even tig wich runs in the console? – bdecaf May 23 '15 at 11:44
  • @bdecaf I took a look at tig. Something like that also looks fine. I just want something running in the console. – ben May 23 '15 at 13:36
  • @ben I've found one more tool, SCM Breeze. This one seems to be more powerful. Have a look ) – Nick Volynkin Jun 17 '15 at 09:04
  • @MichaelDurrant Commits should strive to be atomic rather than contain a huge mass of unrelated changes. Organising modified files into separate commits is a fairly common workflow. – JBentley Feb 14 '19 at 00:47

1 Answers1

20

Example repo:

I'm using an example repo with four files: a, b, c, d.
Here a is tracked, changed and staged; b is tracked, changed and not staged; c in untracked and staged; d is just untracked.

enter image description here

External tool: git-number

When run without arguments, 'git number' runs 'git status' and attach a unique number for each line of filename printed by 'git status', and it will 'remember' this number-to-filename association. When run with arguments, like this:

$ git number <any git command> [one or more numbers or git options/args]

'git number' will run that and subtitute all the numbers to their equivalent filenames. Non-numeric argument are passed intact to git.

enter image description here

This is available with other commands.

enter image description here

External tool: SCM Breeze

SCM Breeze is a set of shell scripts (for bash and zsh) that enhance your interaction with git. It integrates with your shell to give you numbered file shortcuts, a repository index with tab completion, and many other useful features.

SCM Breeze utilizes keyboard shortcuts and aliases to work with git files by number:

Ctrl + x, c => git_add_and_commit - add given files (if any), then commit staged changes

Ctrl + x, Space => git_commit_all - commit everything

git add:

$ ga 1

git diff:

$ gd 2

git reset:

$ grs 3

git commit:

$ gco 4

Native way with git add -i

git add -i

From Git reference:

-i
--interactive
Add modified contents in the working tree interactively to the index. Optional path arguments may be supplied to limit operation to a subset of the working tree. See “Interactive mode” for details.

You can remember this as -intuitive, because the interface is really intuitive. Well, at least to hardcore Vim users.

Opening the interactive mode: enter image description here

Adding (staging) a tracked file: enter image description here

Adding an untracked file: enter image description here

See the changes: enter image description here

If you're stuck in the middle of adding, hit Return with an empty string.

Note:

If you're confused with the appearance and coloring: I've been using iTerm2 + zsh + oh-my-zsh.

Nick Volynkin
  • 14,023
  • 6
  • 43
  • 67
  • As far as i know git -i only allows to add untracked paths to the stage. Does this also allow to add updated files? If not, how would I exclude them from the commit? – Peter Paul Kiefer May 23 '15 at 11:36
  • I've added a tool that does just exactly what you want. – Nick Volynkin May 23 '15 at 11:39
  • 1
    @PeterPaulKiefer: `git add -i` does everything that `git add` can. So, it can add updated files, and remove them. – Jean Hominal May 23 '15 at 11:39
  • @NickVolynkin yep, I think the number tool is the solution. I didnt know of that before. Thank you. – Peter Paul Kiefer May 23 '15 at 11:43
  • Btw, git-number is available in Homebrew, if you're on Mac. – Nick Volynkin May 23 '15 at 11:43
  • @JeanHominal git add only allows to remove files with the --all switch. No chance to select files. But you point me to a problem. You are right, if git add does not allow me to remove files from the stage. How can a avoid commiting them? That is a problem if I intend to add already staged files in seperate commits. git rm --cached could do the job. I think GUIs do it this way. The number tool mentioned by Nick Volynkin could handle this too. – Peter Paul Kiefer May 23 '15 at 11:53
  • 1
    @PeterPaulKiefer use `git reset ` to unstage files. – Nick Volynkin May 23 '15 at 16:47
  • @NickVolynkin Of cause git reset in its simple form is the inverse of git add. I was so stupid. Perhaps because the last time, I often used git reset --hard to throw away some tryouts. – Peter Paul Kiefer May 23 '15 at 18:38
  • My main peeve with interactive add is that it's clunky. There's a lot of boilerplate steps simply to add files by index – void.pointer Jul 21 '16 at 14:05
  • @void.pointer: interactive add is definitely not the best way. – Nick Volynkin Jul 21 '16 at 14:11