Selectively change file settings after renaming

Quite often, when using Git, I will rename the file and then change it:

# Create file and commit
echo 1 > foo
git add .
git commit -m "A"

# Later, rename it
mv foo bar

# Later, modify it    
echo 2 >> bar

Subsequently, I want:

  • rename file
  • selectively stage modifications of the renamed file

However, it git add --patchdoes not provide this option. It asks the user to delete foo(old file name) and add bar(new file name).

Is there a command that I can use to create only renaming, so I can use git add --patchto change individual scenes?


. , git mv , /, git add . - , , IDE.

+4
1

, , git add --interactive ?

, Git . (Mercurial one-hg mv --after, --after git mv, .) , ; , git mv-after, , .

-, Git. Git, , , , Git HEAD, , , , , . Git , . , .

, . -, Git . (.. ) diff, git show, git log -p git status. , Git .

-, , , , , , . :

git rm --cached path/to/file.ext

, , , , , . :

git add path/to/newname.ext

, , . ( , , .) , GUI IDE Git, Git, , , .

git mv --after, :

$ git status
$ program-that-renames-file-and-modifies-it
$ git status --short
 D name.ext
?? newname.ext
$ git mv --after name.ext newname.ext

Git ", name.ext newname.ext ". , :

$ git mv name.ext newname.ext
fatal: bad source, source=name.ext, destination=newname.ext

, :

  • .
  • .
  • git mv .
  • .

:

$ git checkout -- name.ext && \
  mv newname.ext temp-save-it && \
  git mv name.ext newname.ext && \
  mv temp-save-it newname.ext

, (temp-save-it) .

git mv-after

git ls-files --stage, , :

$ git ls-files --stage
100644 038d718da6a1ebbc6a7780a96ed75a70cc2ad6e2 0   README
100644 77df059b7ea5adaf8c7e238fe2a9ce8b18b9a6a6 0   name.ext

, , , . ( , 0 ASCII TAB, 9, .)

, , , ( 0) , . , git update-index. --index-info , , git ls-files --stage .

script, , , " " . :

$ git mv-after name.ext newname.ext
$ git status --short
RM name.ext -> newname.ext

, script - , -A sed - . script - ( ~/scripts/), git-mv-after git mv-after.


#! /bin/sh
#
# mv-after: script to rename a file in the index

. git-sh-setup # for die() etc

TAB=$'\t'

# should probably use OPTIONS_SPEC, but not yet
usage()
{
    echo "usage: git mv-after oldname newname"
    echo "${TAB}oldname must exist in the index; newname must not"
}

case $# in
2) ;;
*) usage 1>&2; exit 1;;
esac

# git ls-files --stage does not test whether the entry is actually
# in the index; it exits with status 0 even if not.  But it outputs
# nothing so we can test that.
#
# We do, however, want to make sure that the file is at stage zero
# (only).
getindex()
{
    local output extra

    output="$(git ls-files --stage -- "$1")"
    [ -z "$output" ] && return 1
    extra="$(echo "$output" | sed 1d)"
    [ -z "$extra" ] || return 1
    set -- $output
    [ $3 == 0 ] || return 1
    printf '%s\n' "$output"
}

# check mode of index entry ($1) against arguments $2...$n
# return true if it matches one of them
check_mode()
{
    local i mode=$(echo "$1" | sed 's/ .*//')

    shift
    for i do
        [ "$mode" = "$i" ] && return 0
    done
    return 1
}

# make sure first entry exists
entry="$(getindex "$1")" || die "fatal: cannot find $1"
# make sure second entry does not
getindex "$2" >/dev/null && die "fatal: $2 already in index"

# make sure the mode is 100644 or 100755, it not clear
# whether this works for anything else and it clearly
# a bad idea to shuffle a gitlink this way.
check_mode "$entry" 100644 100755 || die "fatal: $1 is not a regular file"

# use git update-index to change the name.  Replace the first
# copy mode with 0, and the second copy name with the new name.
# XXX we can't use / as the delimiter in the 2nd sed; use $'\1' as
# an unlikely character
CTLA=$'\1'
printf '%s\n%s\n' "$entry" "$entry" |
    sed -e "1s/100[67][45][45]/000000/" -e "2s$CTLA$TAB.*$CTLA$TAB$2$CTLA" |
    git update-index --index-info
+3

Source: https://habr.com/ru/post/1674878/


All Articles