问题
First, I'm a newbie to git. Like, I could barely tell a cache from an index if it hit me in the staging area. Or something like that. With that out of the way, my problem is this:
Suppose I want to work on a project whose coding style mandates spaces for indentation, but I like tabs. It seems that I can use the clean and smudge features, but there's a catch. The coding style is not followed consistently, and there some files that mix tabs and spaces on the same line. Thus a naïve approach would result in me making a one line change, but accidentally creating a massive commit which brings the project into full compliance with its own standards. This would be great except that the diffs would be less useful so I end up with new enemies.
So the question is: is there a way to get this magic working in such a way that if I don't touch a file, it stays out of the picture? (I'm willing to take full responsibility for the whitespace of files I do touch, even if I change only a single character.)
EDIT: Okay, I just in-accepted the answer I accepted yesterday. I'm pretty sure this is very rude of me. My excuse is that I only got around to testing it today. Since apparently two people misunderstood me already, let me be clear on what I actually did, so maybe someone can tell me if I'm being confused and/or confusing.
$ ls -a
. .. t.txt
$ hd t.txt # file contains 3 bytes: a tab, a capital A, and a newline
00000000 09 41 0a |.A.|
00000003
$ git init
Initialized empty Git repository in /home/marvy/test/.git/
$ git config --local git config --local user.name me
$ git config --local user.email me@example.com
$ git add t.txt
$ git commit
[master (root-commit) 959bf99] testing cleverness of git status
1 file changed, 1 insertion(+)
create mode 100644 t.txt
$ echo '*.txt filter=tabspace' > .git/info/attributes
$ cat .git/info/attributes
*.txt filter=tabspace
$ git config --local filter.tabspace.smudge unexpand
$ git config --local filter.tabspace.clean expand
$ rm t.txt
$ git checkout t.txt
$ git status
On branch master
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: t.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git help --stackoverflow
As we can see here, git status reports that t.txt is modified, even though I just checked it out. If you run git diff, it will claim I want to convert tabs to spaces. Am I doing something wrong?
回答1:
You could use a pre-commit hook and only loop through your edited files and replaces the tabs with spaces. Something like the below:
FILES=`git status -s -uno | egrep '^M' | sed 's/^M//'`
for FILE in $FILES
do
(sed -i 's/[[:space:]]*$//' "$FILE" > /dev/null 2>&1 || sed -i '' -E 's/[[:space:]]*$//' "$FILE")
fi
回答2:
The best way to do it is to use script with smudge-clean
.
smudge-clean
Smudge/Clean are filters which runs wherever a file is passed through the stage area and those filters will modify the file by executing the given script.
Using smudge and clean will touch only the files you pass through the staging area.
For example (unix sample):
If you are unfamiliar with uexpand/unuexpand
read about it
here
~/.gitconfig
# filters to convert between tabs to spaces
[filter "tabspace"]
smudge = unexpand --tabs=2 --first-only
clean = expand --tabs=2 --initial
~/.gitattributes
*.txt filter=tabspace
Now any time you add/checkout files they will be converted based upon your configuration.
You can also take a look on this project in github
回答3:
Setting up the repository:
- Fetch the repository.
- Merge to your local master branch.
Make the big change:
You can change the entire repository if you like. do whatever you want and whatever you need to do. make that one line change which changes everything. But only add the files which you yourself have touched to the "staging area". In other words you'll have to manually add those files:
git add FilesYouWantToAdd.txt
and any other files you are responsible for. Don't add the files you are not responsible for to the staging area.git commit -m 'alter spaces to tabs' // adding only the files you are responsible for.
git push
and you're done.
Discard the other changes:
because nothing substantial in the rest of the files has changed you can simply discard those changes.
git reset HEAD .
It's actually quite simple. Hope this helps.
EDIT:
来源:https://stackoverflow.com/questions/44770689/git-convert-between-tabs-and-spaces-but-only-sometimes