6

I have an entire git repo where I'd like to rename all the files and direcories to lowercase.

Running on Win7, I've added igorecase = false to the gitconfig and renamed a few files through eclipse. The resulting commit now has the two files, one all lowercase and one with upper and lowecase.

Removing the 'undesired' file would dump the version history which is not ideal...

So what is potential method to achieve my goal - thinking only option is batch/shell (not sure how to do recursive directory stuff in there but hopefully someone will be kind ;) )

Any tips recieved with massive thanks and hugs.

joemaller
  • 19,579
  • 7
  • 67
  • 84
Ian Wood
  • 6,515
  • 5
  • 34
  • 73
  • What do you mean by "Removing the 'undesired' file would dump the version history which is not ideal...". git tracks "whole tree" history so if you make a commit that re-cases filenames, no history is lost. – CB Bailey Sep 28 '11 at 10:37
  • 1
    Also, when you `git rm File` and `git add file`, if the files were similar, git detects a rename, which you can see in `git status`. – dmedvinsky Sep 28 '11 at 10:40
  • To clarify. Renaming a file locally then re-scanning shows no changes to be changed. The push is successful and viewing the origin repo (on codebasehq), both files appear in the listings. – Ian Wood Sep 28 '11 at 10:48

3 Answers3

3

When I've had to change case of files in a git repo I just use two renames:

git mv aNiceClass.inc aniceclass.inc_
git mv aniceclass.inc_ aniceclass.inc

Git then happily records the name change:

# Changes to be committed:
#
#   renamed:    aNiceClass.inc -> aniceclass.inc

Trying to do the rename directly throws this error:

fatal: destination exists, source=aNiceClass.inc, destination=aniceclass.inc

Here's an example shell script which will lowercase the name of any file below the current directory which has an inc or txt file extension:

#! /bin/bash

find -E . -regex '.*(inc|txt)$' | while read f
do
   lc=$(echo ${f} | tr A-Z a-z)
   git mv $f ${lc}_
   git mv ${lc}_ $lc
done

That could also be mashed in an ugly little one-liner:

find -E . -regex '.*(inc|txt)$' | while read f; do lc=$(echo ${f} | tr A-Z a-z); git mv $f ${lc}_; git mv ${lc}_ $lc; done
joemaller
  • 19,579
  • 7
  • 67
  • 84
  • 1
    Note: you won't need the script, starting git 2.0.1: http://stackoverflow.com/a/24979063/6309 – VonC Jul 27 '14 at 08:09
2

Since the title or tags doesn't mention anything about OS, this works on macOS. It does a git mv to lowercase on all files in a folder. If you need the force flag just add it in after git mv.

for f in *; do git mv "$f" "`echo $f | tr "[:upper:]" "[:lower:]"`"; done
softarn
  • 5,327
  • 3
  • 40
  • 54
  • 1
    Thanks @softam. Although the OP asked for files and directories", I needed to exclude directories, so I adapted your one-liner to *exclude* directories in case it's helpful to someone: `for f in *; do if [ ! -d "$f" ]; then git mv "$f" "\`echo $f | tr "[:upper:]" "[:lower:]"\`"; fi done` – jbobbins Nov 17 '18 at 19:58
0

For starter, core.ignorecase is false by default.

And your commit should have the two files listed, but one for removal, and one for addition.
Upon commit, Git will detect that one has been renamed into the other
(since Git is at its core a content provider).
The history will be preserved (even though you might need a git log --follow -- yourNewFile in order to get its history)

Note: git 2.0.1 authorizes now a simple git mv a.txt A.txt: see "Git: Changing capitalization of filenames".
No more need for a script like the one below.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Then I've done something drastically wrong. Upon renaming a file, with no edits within that file, re-scan of the repo shows no changes to be staged. – Ian Wood Sep 28 '11 at 10:46
  • @Ian: 're-scan'? you mean a `git status`? – VonC Sep 28 '11 at 10:48
  • yep (I'm lazy - use gui for such) – Ian Wood Sep 28 '11 at 10:50
  • @Ian: did the eclipse rename correctly the files? In case of doubt, whenever a GUI interaction is involved, it is always good to fall back to a CLI (command-line interface), and check in a shell session what a `git status` actually returns. – VonC Sep 28 '11 at 10:56
  • @Ian: anyway, if you end up with two files, a/ this shouldn't be caused by Git, but by Eclipse. b/ you can remove one of those files, as long as the other copy is there. No history will be lost. – VonC Sep 28 '11 at 10:57
  • ace - so back to bulk renaming - am I resigned to a batch file? – Ian Wood Sep 28 '11 at 13:12
  • @Ian: the renaming part (whether it is done with Eclipse or any other way, script or otherwise) should be completely separately from Git. First, make sure Eclipse is able to rename properly those files (with only one file per renaming left, and not two with different cases). Then check that Git detects the changes and commit them appropriately. – VonC Sep 28 '11 at 13:21
  • git is not detecting the changes - I reckon thats the prob! the remote repo shows BOTH files in it listing. I'll keep trying - see if I can find why git is not seeing the changes. – Ian Wood Sep 28 '11 at 13:41
  • @IanWood: but first, is the renaming working (without considering Git). And then, what is the output of `git status`? – VonC Sep 28 '11 at 13:56
  • if I just rename the file (eclipse project browser or just though explorer) the file name has been changed. then running git status : Ok branch dev nothing to commit (working dir clean) – Ian Wood Sep 28 '11 at 14:03
  • @Ian: so you end up with only one file renamed, but git doesn't detect it? – VonC Sep 28 '11 at 14:07
  • Yes, when I actually edit the code in that file, git status results in 2 files (original and one where filename changed to lowercase) being listed in the changes not staged for commit list. Committing and pushing them puts both in remote repo – Ian Wood Sep 28 '11 at 14:11
  • @IanWood: in other word, that status is not "nothing to commit". I would like to see what exact output `git status` gives you when you see those two files. – VonC Sep 28 '11 at 14:57