Skip to content

Commit

Permalink
feat: add rename-file command (#1149)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeByZach authored Aug 2, 2024
1 parent e1a4e71 commit c32869d
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ Patches and Suggestions
- sgleizes
- tfendin
- tiemonl
- Zachary Miller
- zentarul
- zeroDivisible
- zhiyanfoo
Expand Down
15 changes: 15 additions & 0 deletions Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- [`git rebase-patch`](#git-rebase-patch)
- [`git release`](#git-release)
- [`git rename-branch`](#git-rename-branch)
- [`git rename-file`](#git-rename-file)
- [`git rename-tag`](#git-rename-tag)
- [`git rename-remote`](#git-rename-remote)
- [`git repl`](#git-repl)
Expand Down Expand Up @@ -559,6 +560,20 @@ $ git rename-branch old-name new-name
$ git rename-branch new-name
```

## git rename-file

Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
It combines the functionality of the `mv` command and `git mv`. This is particularly useful for renaming files or directories
to change only their case, which might not be detected by Git on case-insensitive filesystems.

```bash
# Rename a file
git rename-file old_filename new_filename

# Rename a directory
git rename-file old_directory new_directory
```

## git rename-tag

Rename a tag (locally and remotely).
Expand Down
101 changes: 101 additions & 0 deletions bin/git-rename-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env bash

set -euo pipefail

# Usage function
usage() {
cat <<EOF
Usage: git rename-file [OPTIONS] <source> <destination>
Description:
Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
It combines the functionality of the "mv" command and "git mv". This is particularly useful for renaming files or directories
to change only their case, which might not be detected by Git on case-insensitive filesystems.
Options:
-h, --help Show this help message and exit.
Examples:
git rename-file old_filename new_filename
git rename-file old_directory new_directory
EOF
}

# Check for help option
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi

# Check for correct number of arguments
if [ "$#" -ne 2 ]; then
echo "Error: Incorrect number of arguments."
echo ""
usage >&2
exit 1
fi

# Assign variables
SOURCE="$1"
DESTINATION="$2"
TEMP_NAME="${SOURCE}.temp"

# Function to check if a file or directory exists in a case-sensitive manner
check_case_sensitive_exists() {
local path="$1"
local dir
local base

dir=$(dirname "$path")
base=$(basename "$path")

if [ -e "$dir" ]; then
if (cd "$dir" && find . -maxdepth 1 -name "$base" | grep -q "$base"); then
return 0
fi
fi
return 1
}

# Check if source exists and is under version control
if ! check_case_sensitive_exists "$SOURCE"; then
echo "Error: Source '$SOURCE' does not exist."
exit 1
fi

if ! git ls-files --error-unmatch "$SOURCE" > /dev/null 2>&1; then
echo "Error: Source '$SOURCE' is not under version control. If file or directory is new, it must at least be staged."
exit 1
fi

# Check if destination already exists
if check_case_sensitive_exists "$DESTINATION"; then
echo "Error: Destination '$DESTINATION' already exists."
exit 1
fi

# Check if the destination directory exists
DEST_DIR=$(dirname "$DESTINATION")
if ! check_case_sensitive_exists "$DEST_DIR"; then
echo "Error: Destination directory '$DEST_DIR' does not exist."
exit 1
fi

# Create a rollback function
rollback() {
echo "Rolling back changes..."
if [ -e "$TEMP_NAME" ]; then
git mv -f "$TEMP_NAME" "$SOURCE"
fi
}

# Trap errors to trigger rollback
trap 'rollback' ERR

# Move the file to a temporary name within the Git repository
git mv "$SOURCE" "$TEMP_NAME"

# Move the temporary file to the desired destination
git mv "$TEMP_NAME" "$DESTINATION"

echo "Successfully renamed '$SOURCE' to '$DESTINATION'."
4 changes: 4 additions & 0 deletions etc/bash_completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,7 @@ _git_browse(){
_git_browse_ci(){
__git_complete_remote_or_refspec
}

_git_rename_file() {
__gitcomp "-h --help"
}
9 changes: 9 additions & 0 deletions etc/git-extras-completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,14 @@ _git-release() {
'--[The arguments listed after "--" separator will be passed to pre/post-release hook.]'
}

_git-rename-file() {
_arguments -C \
'-h[show usage information]' \
'--help[show usage information]' \
'1:source:__git_files' \
'2:destination:__git_files'
}

_git-squash() {
_arguments '--squash-msg[commit with the squashed commit messages]'
_arguments \
Expand Down Expand Up @@ -411,6 +419,7 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
refactor:'create refactor branch' \
release:'commit, tag and push changes to the repository' \
rename-branch:'rename a branch' \
rename-file:'rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity' \
rename-tag:'rename a tag' \
rename-remote:'rename a remote' \
repl:'git read-eval-print-loop' \
Expand Down
3 changes: 3 additions & 0 deletions etc/git-extras.fish
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ set __fish_git_extras_commands \
"rebase-patch:Rebases a patch" \
"release:Commit, tag and push changes to the repository" \
"rename-branch:rename local branch and push to remote" \
"rename-file:rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity" \
"rename-remote:Rename a remote" \
"rename-tag:Rename a tag" \
"repl:git read-eval-print-loop" \
Expand Down Expand Up @@ -180,6 +181,8 @@ complete -c git -n '__fish_git_using_command merge-into' -l ff-only -d 'merge on
complete -c git -x -n '__fish_git_using_command merge-into' -a '(__fish_git_branches)'
# missing
complete -c git -x -n '__fish_git_using_command missing' -a '(__fish_git_branches)'
# rename-file
complete -c git -f -n '__fish_git_using_command rename-file' -s h -l help -d 'Show usage information'
# squash
complete -c git -x -n '__fish_git_using_command squash' -a '(__fish_git_branches)'
complete -c git -x -n '__fish_git_using_command squash' -l squash-msg -d 'commit with the squashed commit messages'
Expand Down
1 change: 1 addition & 0 deletions man/git-extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ git-extras(1) -- Awesome GIT utilities
- **git-rebase-patch(1)** Rebases a patch
- **git-release(1)** Commit, tag and push changes to the repository
- **git-rename-branch(1)** rename local branch and push to remote
- **git-rename-file(1)** CRename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
- **git-rename-remote(1)** Rename a remote
- **git-rename-tag(1)** Rename a tag
- **git-repl(1)** git read-eval-print-loop
Expand Down
30 changes: 30 additions & 0 deletions man/git-rename-file.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.\" generated with Ronn-NG/v0.8.0
.\" http://github.com/apjanke/ronn-ng/tree/0.8.0
.TH "GIT\-RENAME\-FILE" "1" "July 2024" "" "Git Extras"
.SH "NAME"
\fBgit\-rename\-file\fR \- Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
.SH "SYNOPSIS"
\fBgit\-rename\-file\fR [OPTIONS] <source> <destination>
.SH "DESCRIPTION"
The \fBgit\-rename\-file\fR command renames a file or directory and ensures Git recognizes the change, regardless of filesystem case-sensitivity. It combines the functionality of the \fBmv\fR command and \fBgit mv\fR.
This is particularly useful for renaming files or directories to change only their case, which might not be detected by Git on case-insensitive filesystems.
.SH "OPTIONS"
\fB\-h\fR, \fB\-\-help\fR
.RS
Show usage information.
.RE
.SH "EXAMPLES"
Rename a file:
.RS
\fBgit\-rename\-file old_filename new_filename\fR
.RE
Rename a directory:
.RS
\fBgit\-rename\-file old_directory new_directory\fR
.RE
.SH "AUTHOR"
Written by Zachary Miller <\fI\%[email protected]\fR>
.SH "REPORTING BUGS"
<\fI\%https://github.com/tj/git-extras/issues\fR>
.SH "SEE ALSO"
<\fI\%https://github.com/tj/git-extras\fR>
106 changes: 106 additions & 0 deletions man/git-rename-file.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions man/git-rename-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
git-rename-file(1) -- Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
================================================

## SYNOPSIS

`git-rename-file` [OPTIONS] <source> <destination>

## DESCRIPTION

The `git-rename-file` command renames a file or directory and ensures Git recognizes the change, regardless of filesystem case-sensitivity. It combines the functionality of the `mv` command and `git mv`.

This is particularly useful for renaming files or directories to change only their case, which might not be detected by Git on case-insensitive filesystems.

## OPTIONS

-h, --help
Show usage information.

## EXAMPLES

Rename a file:

```sh
git-rename-file old_filename new_filename
```

Rename a directory:

```sh
git-rename-file old_directory new_directory
```

## AUTHOR

Written by Zachary Miller &lt;<[email protected]>&gt;

## REPORTING BUGS

<https://github.com/tj/git-extras/issues>

## SEE ALSO

<https://github.com/tj/git-extras>
1 change: 1 addition & 0 deletions man/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ git-reauthor(1) git-reauthor
git-rebase-patch(1) git-rebase-patch
git-release(1) git-release
git-rename-branch(1) git-rename-branch
git-rename-file(1) git-rename-file
git-rename-remote(1) git-rename-remote
git-rename-tag(1) git-rename-tag
git-repl(1) git-repl
Expand Down

0 comments on commit c32869d

Please sign in to comment.