8

I have tons of files in my repo, and sometimes I work on 20 files and I want to commit all of them. But, I would like to add a message for each.

How can I add all of these files that have been updated and also add a message for each without having do run a command for each one manually? Is this possible to do a bulk run and have it prompt me to add a message for each one?

Nic Hubbard
  • 41,587
  • 63
  • 251
  • 412

3 Answers3

10

(A note: You shouldn’t think about individual files, nor should you commit a dozen unrelated changes at once. Think about your changes in terms of logical groups. You can commit as you go, or you can commit each file one at a time. But really try to make one conceptual change, commit it, and move on to something else.)

If you have lots of changed files, you can just add them all and use git commit, for the editor window contains a list of changed files which you can incorporate into your commit message. But if you want to be prompted for each one, you can loop through them and commit them individually, then squash those into a single commit.

  • Write down where you are; we will squash on top of this later:

    $ git rev-parse HEAD
    57c1df83f140b2dedbdf8a44ee623654d37bd1c3 
    
  • Loop through the modified files (note that untracked files are not considered here) and commit each one individually:

    $ for file in $(git ls-files)
    >   do git add $file
    >   git commit  # Write a commit message for the file.
    >               # It might be a good idea to use a format like "filename: changes"
    > done
    
  • Squash everything:

    $ git rebase -i 57c1df83f140b2dedbdf8a44ee623654d37bd1c3
    

    Change every line but the first from pick to squash, then save and quit.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • 1
    Your point about making small commits each with a logical change is well made. I really don't see the point of creating lots of commits and then squashing them into one in this case, though... – Mark Longair Mar 02 '11 at 20:49
  • There really isn’t a point; it’s just a way to be prompted for each file. – Josh Lee Mar 02 '11 at 22:04
8

I would recommend doing a commit for each one. However, you can automate the process by using a small shell script.

For example:

#!/bin/sh

PROJECT_DIR=.

for FILE in ${PROJECT_DIR}/*
do
    git add ${FILE}
    git commit
done

In it's current form, the script considers the current working directory the PROJECT_DIR. It then iterates through all files (that match the * glob), adding and commiting them individually to the repository. Unchanged files are skipped by git and for each changed file your editor will fire up to prompt you for a commit message.

If you're prompted to comment on a file you do not want to commit yet, just save the commit message file without any changes and git will skip over it.

chuckx
  • 6,484
  • 1
  • 22
  • 23
  • I just find it annoying to have to commit each one every time I had made changes. Oh well, I guess that is the nature of it. – Nic Hubbard Mar 02 '11 at 17:52
  • You could add message files and use 'git commit -F ${FILE}_msg' Possibly more work though... – Karl Mar 02 '11 at 22:16
  • 1
    I recommend: git commit -m "initial commit ${FILE}" – Josh Russo Jul 09 '11 at 03:25
  • btw, thanks for the script, gotta love simplicity, but when you have an existing project you want to add to a repo -m is your friend. ;o) – Josh Russo Jul 09 '11 at 03:27
  • please does anyone know the solemn difference between -a and -am when commiting because am really getting confused – DaMainBoss Jul 18 '11 at 02:14
  • '-a' automatically stages all modified and deleted files (but not new files unknown by the repository. '-m' takes an argument and allows you to specify a commit message on the command line. They are two separate functions with no overlap, so they don't modify one another when presented together. – chuckx Jul 23 '11 at 20:04
0
A variation on the loop suggested above...
#!/bin/sh
git reset *
PROJECT_DIR=.
for FILE in ${PROJECT_DIR}/*
do
    echo ${FILE}
    git add -f ${FILE}
    git commit -m 'bulk edit'
done

Execute on a separate branch then each commit can be cherry picked and commented on.

  • the files that were not supposed to be added shouldn't get cherry picked into the target branch.
36d634bfb (HEAD -> 14JUL2021-rebase-begin) bulk edit
8cd0b4549 bulk edit
ed95d7137 bulk edit
0a384dbc1 bulk edit
5822b5351 bulk edit
ab4fe08cc bulk edit
b2ae84d54 bulk edit
ff2544952 bulk edit
...
473dd9017 bulk edit
a2eb707e2 bulk edit
b9dbc34f5 bulk edit
c3ebc2f73 bulk edit
04787f1ab bulk edit
51c6838d6 bulk edit
cee32c368 bulk edit
8f12dbbb7 bulk edit
0ed3d63bf bulk edit
...
RandyMcMillan
  • 59
  • 2
  • 3