15

I need to take a bunch of files that have changed and scp them to different boxes for testing. I'm having trouble figuring out how to make git status give me a listing like ls -1 so I can script the actions with minimal effort.

I have an existing script that does what I need using ls -1. I'm not a gifted scripter, so I don't want to modify the script. Instead, I would like the tool to modify its output.

Obviously, git status -1 did not work. The format in How can I get 'git status' to always use short format is not compatible with my script. And git status --column produced the same result as below.

How do I have git status list modified files, one to a line, with only the modified file on the line?


$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

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

    modified:   cryptest.vcproj
    modified:   dlltest.vcproj

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:   adler32.cpp
    modified:   algebra.cpp
    modified:   algparam.cpp
    modified:   asn.cpp
    modified:   asn.h
    modified:   authenc.cpp
    modified:   authenc.h
    modified:   basecode.cpp
    modified:   cast.cpp
    modified:   ccm.cpp
    modified:   cmac.cpp
    modified:   config.h
    modified:   cryptdll.vcproj
    modified:   cryptlib.cpp
    modified:   cryptlib.h
    modified:   cryptlib.vcproj
    modified:   datatest.cpp
    modified:   dlltest.cpp
    modified:   eax.cpp
    modified:   ec2n.cpp
    modified:   eccrypto.cpp
    modified:   ecp.cpp
    modified:   emsa2.cpp
    modified:   eprecomp.cpp
    modified:   esign.cpp
    modified:   files.cpp
    modified:   filters.cpp
    modified:   filters.h
    modified:   fips140.cpp
    modified:   fipsalgt.cpp
    modified:   fltrimpl.h
    modified:   gf2_32.cpp
    modified:   gf2n.cpp
    modified:   gf2n.h
    modified:   gfpcrypt.cpp
    modified:   gfpcrypt.h
    modified:   hkdf.h
    modified:   hmac.cpp
    modified:   hrtimer.cpp
    modified:   ida.cpp
    modified:   idea.cpp
    modified:   integer.cpp
    modified:   iterhash.cpp
    modified:   luc.h
    modified:   misc.cpp
    modified:   misc.h
    modified:   modes.cpp
    modified:   modes.h
    modified:   nbtheory.cpp
    modified:   network.cpp
    modified:   oaep.cpp
    modified:   panama.cpp
    modified:   pkcspad.cpp
    modified:   polynomi.cpp
    modified:   pssr.cpp
    modified:   pubkey.h
    modified:   pwdbased.h
    modified:   queue.cpp
    modified:   rijndael.cpp
    modified:   rsa.cpp
    modified:   rw.cpp
    modified:   salsa.cpp
    modified:   seal.cpp
    modified:   secblock.h
    modified:   simple.h
    modified:   smartptr.h
    modified:   socketft.cpp
    modified:   socketft.h
    modified:   sosemanuk.cpp
    modified:   strciphr.cpp
    modified:   strciphr.h
    modified:   test.cpp
    modified:   validat1.cpp
    modified:   validat2.cpp
    modified:   vmac.cpp
    modified:   wait.cpp
    modified:   winpipes.cpp
    modified:   winpipes.h
    modified:   words.h
    modified:   xtr.cpp
    modified:   xtr.h
    modified:   zdeflate.cpp
    modified:   zinflate.cpp
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885

5 Answers5

12

git status --porcelain

This will output in short format but will be consistent across all versions of Git.

git-status documentation

Here is an excerpt from the reference:

--porcelain
Give the output in an easy-to-parse format for scripts. This is similar to the short output, but will remain stable across Git versions and regardless of user configuration.

Thomas Stringer
  • 5,682
  • 3
  • 24
  • 40
  • This still doesn't replicate the output of `ls -1`. Care to expand your answer a wee bit? – ghoti Jul 20 '15 at 18:35
  • Thanks. Its close, but there are additional characters on the line. I want one file listed on one line. – jww Jul 20 '15 at 18:37
  • Unfortunately I don't think you can that output trimmed down anymore. `git-status` doesn't just list files. It gives much more information than that, so outside of shortening the output with that option your best bet (and only option, I think) is to just have custom parsing logic. – Thomas Stringer Jul 20 '15 at 18:38
  • 1
    @Thomas - why does that not surprise me.... Git takes every simple tasks and makes you work for the result... I'll just award the answer to you since its another Git gap. You should not be penalized for the tool's short comings. – jww Jul 20 '15 at 18:40
  • `git status --porcelain` outputs all differences between working directory and repository — so the untracked files too. So without some grepping your answer is incomplete. – werkritter Jul 21 '15 at 07:50
  • @jww: There's a better answer below: http://stackoverflow.com/a/35865151/1450294 I'm not sure it's appropriate to penalise Thomas for sharing the best answer he knew, but it's more appropriate than an unfair remark about git! – Michael Scheper May 18 '17 at 19:10
8

If you have unstaged changes, you can list all the touched files in a one-column list similar to ls -1 with this command:

git ls-files --modified --others --exclude-standard --directory

The --modified option shows modified files and the --others option shows other untracked files such as new files; --exclude-standard ignores excluded files and --directory lists only directory names and not the files inside them. Refer to the documentation for more information.

Here's the command I use to quickly copy all modified and new files to my temp directory while preserving the full directory path (a dirty alternative to git stash):

git ls-files --modified --others --exclude-standard --directory | xargs -I {} cp --parents {} ~/temp

If you have already added the files to git to be committed (e.g., git add -A .), then you can use the command in the accepted answer and extract the second column to get your plain list of files:

git status --porcelain | awk '{ print $2 }'

If you want to filter the rows by git status, then you can do something like this:

git status --porcelain | grep ^[AM] | awk '{ print $2 }'

This gives you a list containing only modified (M) and newly added (A) files.


Updates:

  • Added @jotik's suggestion.
thdoan
  • 18,421
  • 1
  • 62
  • 57
  • 1
    `git ls-files --modified --others --exclude-standard --directory` might give more better output, by taking git exclusion files into account and not recursing into directories not under version control. – jotik Mar 08 '16 at 10:47
4

For modified file list, the following commands can be a help.

git diff --name-only

or

git diff --name-status

int the output of --name-status, the status(A, M, D) and file pathname is separated by tab, you can parse it by cut command.

If you can to get file list on staging too, `--cache' option can be used.

gzh
  • 3,507
  • 2
  • 19
  • 23
3

As Thomas suggested, the --porcelain option is the thing you want. But of course, to get JUST the filename of modified files, you need to parse that output as well. For example, piping the output through a simple sed script like this may work:

git status --porcelain | sed -ne '/^M  */s///p'

This script searches for a M and whitespace at the beginning of the line. If they are found, they are removed and the line is printed. If they are not found (i.e. the output is something other than a Modified file), no output is shown.

The output of the command line above should be just about equivalent to what you get from ls -1 -- that is, a list of files, with no other information. Note that --porcelain terminates filenames with a NULL, so if the output does not function as you expect, you may need to handle that in your script, or in another pipe. (Read about xargs(1)).

ghoti
  • 45,319
  • 8
  • 65
  • 104
  • Your answer doesn't cover all cases. Only fully staged files have output from `git status --porcelain` that is handled by your `sed`. If a given file was modified, but unstaged, the output would look like this" ` M an_unstaged_file` (with space at the beginning). Even better, if file had both staged and unstaged parts, the output would be `MM an_unstaged_and_staged_file`. – werkritter Jul 21 '15 at 07:54
-1

To detect changed files and scp them directly to the remote server :

scp `git status --porcelain | cut -c 4-` bb:~/${PWD##*/}
Ahmed
  • 689
  • 6
  • 14