如何合并git diff --name-status和git diff --stat命令的输出?

时间:2018-06-26 16:40:30

标签: git diff

使用git diff --name-status命令,我可以看到文件状态如下的文件名:

M       .bashrc
D       .ghc/.ghci.conf.un~
D       .ghc/ghci_history
M       .life
A       .profile
M       .spacemacs

使用git diff --stat,我可以看到行数和文件更改的统计信息:

 .bashrc             |   3 ++-
 .ghc/.ghci.conf.un~ | Bin 13912 -> 0 bytes
 .ghc/ghci_history   | 100 --------------------------------------------------------------------------------------------
 .life               |   2 ++
 .profile            |  23 +++++++++++++++++++++
 .spacemacs          |   3 +++

有没有办法组合两个命令的输出?我想要这样的东西:

M  .bashrc             |   3 ++-
D  .ghc/.ghci.conf.un~ | Bin 13912 -> 0 bytes
D  .ghc/ghci_history   | 100 --------------------------------------------------------------------------------------------
M  .life               |   2 ++
A  .profile            |  23 +++++++++++++++++++++
M  .spacemacs          |   3 +++

当然,我可以通过同时调用两个命令的字符串然后操作字符串来手动完成此操作。但是我不确定这些命令的输出如何可靠和一致。也许它记录在某个地方。

3 个答案:

答案 0 :(得分:3)

DIFF=origin/master..HEAD
join -t $'\t' -1 2 -2 1 -o 1.1,2.1,2.2 \
        <(git diff --name-status $DIFF | sort -k2)
        <(git diff --stat=$((COLUMNS-4)),800 $DIFF | sed -e '$d' -e 's/^ *//;s/ /\t/' | sort) \
        | sed 's/\t/ /g'

或者,在[alias]的{​​{1}}部分中完全使用POSIX

~/.gitconfig
ndiff = "!f() { TAB=`printf '\t'`; COLUMNS=`stty size|cut -d' ' -f2`; cd $GIT_PREFIX; git diff --name-status $1 | sort -k2 > /tmp/.tmpgitndiff ; git diff --stat=$COLUMNS,800 $1 |sed -e '$d' -e \"s/^ *//;s/ /${TAB}/\" | sort | join -t \"${TAB}\" -1 2 -2 1 -o 1.1,2.1,2.2 /tmp/.tmpgitndiff - | sed \"s/${TAB}/ /g\"; rm -f /tmp/.tmpgitndiff; }; f"

答案 1 :(得分:2)

最简单的方法是使用wdiff

$ wdiff -n -w '' -x '' -y '' -z '' <(git diff --name-status) <(git diff --stat)
vvv 2018-06-26 10:08:27-0700
M       foo/baz.py   | 19 +++++++++++--------
M       foo/bar.py   | 37 ++++++++-----------------------------
M       foo/qux.py   |  2 +-
 3 files changed, 20 insertions(+), 38 deletions(-)

-[w-z]选项设置插入/删除开始/结束的分隔符。

-n确保输出是按行的... ...传递-[w-z]时可能并不重要,但通常是wdiff的好习惯。

从理论上讲,如果您的文件名看起来像行中的其他任何文件,则容易出错。幸运的是,优良作法往往会避开M|19+++++++++++--------

这样的文件名

更正确的方法是使用paste,但这将需要随后将输出通过sed来删除重复的部分。

答案 2 :(得分:1)

您还可以使用for循环来过滤每种可能状态的输出:

for filter in A C D M R T U X B; do git diff --diff-filter="$filter" --stat | head -n -1 | sed "s/.*/$filter &/"; done;
  • --diff-filter确保仅显示当前状态的文件(例如,仅显示[A] dd个文件)
  • --stat显示您想要的状态
  • head命令然后删除每个统计信息输出的最后一行(例如x files changed, n deletions
  • 最后,sed命令将当前过滤器插入开头(例如A

这确实意味着您始终会根据文件的状态而不是仅通过git命令对其进行排序的方式来对文件进行排序。

编辑

如@Shersh在评论中所述,tail -n在macOS上不适用于负整数。有两种解决方案:

  1. 要么安装ghead:brew install coreutils(在this answer中获得jchook的评论)
  2. 或使用tac反转行,从第二行以tail -n +2开始,然后再次以tac反转:
for filter in A C D M R T U X B; do git diff --diff-filter="$filter" --stat | tac | tail -n +2 | tac | sed "s/.*/$filter &/"; done;

Ps。除了使用tac以外,您还可以使用tail -r,但这并不在所有系统上都有效,并且您会失去对齐(请参阅@Shersh的评论,无法在我的系统上进行测试)。