“git status” in brief or short format like “ls -1”

2019-06-16 17:36发布

问题:

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

回答1:

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.



回答2:

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.


回答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)).



回答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.



回答5:

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

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