Git:トピックブランチで変更されるファイルをリスト表示するコマンド

トピックブランチで変更されるファイルを一覧表示するコマンドを作ったので紹介する。

```bash
# 直近のマージコミットのコミットハッシュを探す
LAST_MERGE_COMMIT_HASH=$(git rev-list -1 --merges HEAD)
# 直近のマージコミット以降に変更されたファイル一覧を取得する
TRACKED_FILES_IN_TOPIC_BRANCH=$(git diff ${LAST_MERGE_COMMIT_HASH} --staged --name-only)
# Gitで追跡されていないファイル一覧を取得する
UNTRACKED_FILES_IN_TOPIC_BRANCH=$(git ls-files . --exclude-standard --others)
# そのふたつを合わせ、ソートし、存在するファイルだけにフィルタリングして、出力する
{
	echo ${TRACKED_FILES_IN_TOPIC_BRANCH}
	echo ${UNTRACKED_FILES_IN_TOPIC_BRANCH}
}  | sort  | xargs ls -1 2>/dev/null
```


## テストコード

```bash
#!/bin/bash

set -eux

: "Prepare repository" && {	
	test -d myapp && rm -rf myapp
	mkdir myapp
	cd myapp
	git init
	git commit --allow-empty --message 'initinalize repository'
}

: "Create merge commit" && {
	git checkout -b topic-1
	touch 1m 1d 1r 2m 2d 2r 3
	git add 1m 1d 1r 2m 2d 2r 3
	git commit --message 'add files'
	git checkout master
	git merge --no-ff --no-edit topic-1 
}

: "I start new topic branch" && {
	git checkout -b topic-2

	: "I want to change and COMMIT files that start with 1" && {
		: "I add a file" && 	touch 1a
		: "I modify the file in the previous topic branch" && echo "test" > 1m
		: "I delete the file in the previous topic branch" && rm 1d
		: "I rename the file in the previous topic branch" && mv 1r 1r-renamed
		: "Then I commit them" && {
			git add .
			git commit --message 'change files #1'
		}
	}
	
	: "I want to add new files into current topic branch (I will change them later)" && {
		: "I add new files" && touch 4a 4m 4d 4r
		: "And I commit them" && git add . && git commit --message 'add files #4'		
	}
	
	: "I want to add new files into current topic branch (I will not change them!)" && {
		: "I add new files" && touch 7
		: "And I commit them" && git add . && git commit --message 'add files #7'		
	}
	
	: "I want to change and STAGE files that I have added above" && {
		: "I modify the file" && echo "test" > 4m
		: "I delete the file" && rm 4d
		: "I rename the file" && mv 4r 4r-renamed
		: "Then I stage them" && {
			git add .
		}
	}

	: "I want to change and STAGE files that start with 2" && {
		: "I add a file" && touch 2a
		: "I modify the file in the previous topic branch" && echo "test" > 2m
		: "I delete the file in the previous topic branch" && rm 2d
		: "I rename the file in the previous topic branch" && mv 2r 2r-renamed
		: "Then I stage them" && {
			git add .
		}
	}

	: "I DON'T want to change the files that start with '3'" && {
		ls 3*
	}

	: "I want just STAGE new files and change them" && {
		: "I add new files" && touch 5a 5m 5d 5r
		: "And I stage them" && git add .
		: "Then I change them (I don't stage them yet)" && {
			: "I modify the file" && echo "test" > 5m
			: "I delete the file" && rm 5d
			: "I rename the file" && mv 5r 5r-renamed
		} 
	}
	
	: "I want create untracked file" && touch 6-untracked
}

git status -s

git-diff-topic-branch () {
	LAST_MERGE_COMMIT_HASH=$(git rev-list -1 --merges HEAD)
	TRACKED_FILES_IN_TOPIC_BRANCH=$(git diff ${LAST_MERGE_COMMIT_HASH} --staged --name-only)
	UNTRACKED_FILES_IN_TOPIC_BRANCH=$(git ls-files . --exclude-standard --others)
	{
		echo ${TRACKED_FILES_IN_TOPIC_BRANCH}
		echo ${UNTRACKED_FILES_IN_TOPIC_BRANCH}
	}  | sort  | xargs ls -1 2>/dev/null
}

# test
[ "$(git-diff-topic-branch)" == \
"1a
1m
1r-renamed
2a
2m
2r-renamed
4a
4m
4r-renamed
5a
5m
5r-renamed
6-untracked
7" ] || { 
	echo "FAIL"
	exit 1 
}
```