programing

git가 경로별로 하드/소프트 재설정을 수행할 수 없는 이유는 무엇입니까?

oldcodes 2023. 6. 23. 22:25
반응형

git가 경로별로 하드/소프트 재설정을 수행할 수 없는 이유는 무엇입니까?

$ git reset -- <file_path>경로로 재설정할 수 있습니다.

하만지,$ git reset (--hard|--soft) <file_path>다음과 같은 오류가 보고됩니다.

Cannot do hard|soft reset with paths.

의미가 없기 때문에(다른 명령은 이미 해당 기능을 제공합니다), 실수로 잘못된 작업을 수행할 가능성이 줄어듭니다.

" 리셋은 " 리셋"을 사용하여 수행됩니다.git checkout HEAD -- <path>(파일의 기존 버전 체크아웃).

경로에 대한 소프트 재설정은 의미가 없습니다.

경로에 대한 혼합 재설정은 다음과 같습니다.git reset -- <path> 그렇습니다.

사용하여 수행하려는 작업을 수행할 수 있습니다.git checkout HEAD <path>.

.git reset잘함), 저는 왜 그런지 를 알 수 .git reset --hard당신이 요구하는 것을 정확히 해서는 안 됩니다.

어떻게 답이 나왔는지, 왜 그런지 설명해드리겠습니다.

그럼, git reset은 무슨 일을 할까요?지정된 매개 변수에 따라 두 가지 작업을 수행할 수 있습니다.

  • 경로를 지정하면 인덱스에서 일치하는 파일이 커밋의 파일(기본적으로 HEAD)로 바뀝니다.이 동작은 작업 트리에 전혀 영향을 주지 않으며 일반적으로 gitadd의 반대로 사용됩니다.

  • 경로를 지정하지 않으면 현재 분기 헤드가 지정된 커밋으로 이동하고 선택적으로 인덱스와 작업 트리를 해당 커밋의 상태로 재설정합니다.추가 동작은 모드 파라미터에 의해 제어됩니다.
    --soft: 인덱스와 작업 트리를 만지지 마십시오.
    --mixed(기본값): 인덱스를 재설정하지만 작업 트리는 재설정하지 않습니다.
    --hard: 인덱스와 작업 트리를 재설정합니다.
    다른 옵션도 있습니다. 전체 목록 및 일부 사용 사례에 대한 설명서를 참조하십시오.

    커밋을 지정하지 않으면 HEAD로 기본 설정됩니다.git reset --soft헤드를 HEAD(현재 상태)로 이동하는 명령이므로 아무 작업도 수행하지 않습니다. git reset --hard반면에 부작용 때문에 말이 되네요, 헤드를 HEAD로 이동하고 인덱스와 작업 트리를 HEAD로 재설정한다고 합니다.

    이 작업이 특정 파일에 대한 작업이 아닌 이유는 지금쯤 명확해야 한다고 생각합니다. 처음부터 분기 헤드를 이동하여 작업 트리를 재설정하고 인덱스는 보조 기능입니다.

그 이면에는 매우 중요한 이유가 있습니다. 바로 와 의 원칙입니다.

Git 용어로 체크아웃은 "현재 작업 트리로 가져오기"를 의미합니다.그리고 함께git checkout저장소의 커밋 또는 스테이징 영역(기본값인 경우에도)의 개별 파일이나 저장소의 커밋 데이터를 사용하여 작업 트리를 채울 수 있습니다.

반대로, git reset에는 이 역할이 없습니다.이름에서 알 수 있듯이 현재 참조는 재설정되지만 "reach"(--soft, --mixed 또는 --hard)와 관계없이 항상 리포지토리를 소스로 사용합니다.

요약:

  • 체크아웃:어디서든 (인덱스 / 재포커밋) -> 작업 트리
  • reset: Repo commit -> HEAD 덮어쓰기 (및 선택적으로 인덱스 및 작업 트리)

그러므로 약간 혼란스러울 수 있는 것은 존재하는 것입니다.git reset COMMIT -- files일부 파일로만 "헤드를 덮어쓰는" 것은 말이 안 되기 때문입니다!

공식적인 설명이 없는 상황에서, 나는 Git 개발자들이 그것을 발견했다는 것을 추측할 수 있을 뿐입니다.reset는 여전히 준비 영역에 대한 변경 사항을 삭제하는 데 가장 적합한 명령 이름이었으며, 유일한 데이터 소스가 리포지토리였기 때문에 새 명령을 만드는 대신 "기능을 확장합시다"라고 말했습니다.

그래서 어떻게든git reset -- <files>는 이미 약간 예외적입니다. HEAD . 입니다.IMHO는 이러한 모든 변형은 예외일 것입니다.우리가 상상할 수 있을지라도--hard: 버전, 기예):--soft이 안 말이 안 됩니다.

오리진 또는 업스트림(소스)과 실제 분기 사이에 슬래시를 넣으십시오.

git reset --hard origin/branch

또는

git reset --hard upstream/branch`

이 대답은 이제 제가 여기서 더 광범위하게 대답한 것으로 참조됩니다: 모든 것은 파일이나 디렉터리를 체크아웃하는 입니다.

git가 경로별로 하드/소프트 재설정을 수행할 수 없는 이유는 무엇입니까?

할 수 있습니다. 하나가 아니라 여러 개의 명령만 있으면 됩니다.방법은 다음과 같습니다.

요약

예: git status이 프로세스를 시작하기 전에 완전히 청소해야 합니다!그렇지 않으면 다음에 표시된 커밋되지 않은 변경 사항이 영구적으로 손실될 위험이 있습니다.git status로, 터부git clean -fd'force'는 현재 작업 트리(파일 시스템)에 있지만 아래 커밋 또는 분기에서 지정한 경로에는 없는 모든 파일 및 'd' 디렉터리를 삭제합니다.commit_hash따라서 아직 커밋되지 않은 항목은 사용한 것처럼 영구적으로 손실됩니다.rm 작시!

--soft경로별 재설정:

# How to "soft reset" "path/to/some/file_or_dir" to its state exactly as it was
# at commit or branch `commit_hash`.
#
# SEE WARNING ABOVE!

git reset commit_hash -- path/to/some/file_or_dir
git checkout-index -fa
git clean -fd  # SEE WARNING ABOVE!

--hard경로별 재설정:

# How to "hard reset" "path/to/some/file_or_dir" to its state exactly as it was
# at commit or branch `commit_hash`.
#
# SEE WARNING ABOVE!

git reset commit_hash -- path/to/some/file_or_dir
git checkout-index -fa
git clean -fd  # SEE WARNING ABOVE!
git commit -m "hard reset path/to/some/file_or_dir to its state \
as it was at commit_hash"

전체 답변:

2됨(Git 버 2.17.1에서 )git --version).

git가 경로별로 하드/소프트 재설정을 수행할 수 없는 이유는 무엇입니까?

정확한 이유는 모르겠지만, 아마도git당신과 내가 둘 다 동의하지 않는 개발 결정을 했거나, 아니면 때문에.git단순히 불완전하며, 여전히 이를 구현해야 합니다.된 " 된▁the--hard아래 "경로별로 재설정" 섹션. --hard단일 경로에서 재설정은 a와 동일한 방식으로 수행할 수 없습니다.--hard전체 분기에 대해 재설정합니다.

그러나 몇 가지 명령을 사용하여 원하는 동작을 수동으로 수행할 수 있습니다.:git checkout commit_hash -- path/to/some/file_or_dir아래에 설명된 이유로 인해 단독으로는 해당되지 않습니다.

전에 여러분은 .git reset수행, 작업 트리, 인덱스 및 작업 항목--soft그리고.--hard은 통적으하는으로 .git reset이러한 항목에 대해 질문이 있는 경우 아래의 "배경 지식" 섹션을 먼저 읽으십시오.

--soft또는--hard경로별 git 재설정

AKA: 다음과 같은 잘못된 명령 중 하나를 수동으로 실행하는 방법:

# hypothetical commands not allowed in git, since `git` does NOT 
# allow `--soft` or `--hard` resets on paths

git reset --soft commit_hash -- path/to/some/file_or_dir
git reset --hard commit_hash -- path/to/some/file_or_dir

되지 않기 에, 이 명령어 로, 이 명령어는 사용할 수 없습니다.checkout명령은 의 가상 명령이 수행하는 것과 동일하지 않습니다. 이는 다음과 같습니다.checkout명령은 또한 로컬에 존재하지 않는 파일이나 폴더를 삭제하지 않습니다.commit_hash:

git checkout commit_hash -- path/to/some/file_or_dir

...그러면 위의 가상 명령이 아래의 여러 명령으로 수행하는 작업을 함께 수행할 수 있습니다.

1. --soft

설명:로컬로 만들기path/to/some/file_or_dir와 한.file_or_dir을다에 있는 것처럼 .commit_hash디렉터리의 에도 (만약 "" "" "" "" " " " "일 경우")path/to/some/file_or_dir는디리에존않디는다니의 입니다.commit_hash모든 변경사항은 마지막에 "staged"(추가되었지만 커밋되지 않음)로 둡니다.

git reset commit_hash -- path/to/some/file_or_dir
git checkout-index -fa
git clean -fd

위의 결과는 정확히 제가 기대하는 것입니다.--soft이러한 명령이 허용된 경우 경로에서 재설정됩니다.

에대자한내참용오시십조하에 .git checkout-index -fa그리고.git clean -fd부품, 여기에 있는 다른 답변을 참조하십시오. git을 사용하여 작업 트리(로컬 파일 시스템 상태)를 인덱스 상태("단계화된" 파일)로 재설정하려면 어떻게 해야 합니까?

각 명령을 실행한 후 를 실행하여 각 명령이 수행 중인 작업을 확인해야 합니다.다음은 개별 명령에 대한 설명입니다.

# Stage some changes in path/to/some/file_or_dir, by adding them to the index,
# to show how your local path/to/some/file_or_dir SHOULD look in order to
# match what it looks like at `commit_hash`, but do NOT actually _make_ 
# those changes in yourlocal file system. Rather, simply "untrack" files 
# which should be deleted, and do NOT stage for commit changes which should 
# NOT have been made in order to match what's in `commit_hash`.
git reset commit_hash -- path/to/some/file_or_dir
git status

# Now, delete and discard all your unstaged changes.

# First, copy your index (staged/added changes) to your working file 
# tree (local file system). See this answer for these details:
# https://stackoverflow.com/a/66589020/4561887
# and https://stackoverflow.com/a/12184274/4561887
git checkout-index -fa
git status

# 'f'orce clean, including 'd'irectories. This means to **delete** 
# untracked local files and folders. The `git reset` command above
# is what made these untracked. `git clean -fd` is what actually 
# removes them.
git clean -fd
git status

2. --hard

설명:실행--soft위의 단계를 재설정한 다음 변경 내용도 커밋합니다.

git reset commit_hash -- path/to/some/file_or_dir
git checkout-index -fa
git clean -fd
git commit -m "hard reset path/to/some/file_or_dir to its state \
as it was at commit_hash"

자, 좋은 , 은 이제적측최점수있다습니실위할을 할 수 .git reset commit_hash -- path/to/some/file_or_dir에 뒤에git status는 것을 알게 될 것입니다.git status아무런 변화도 보이지 않습니다, 왜냐하면--hard이 위에서 에 이 은 "" " " " " " " " 에 대한 호출입니다.git reset commit_hash -- path/to/some/file_or_dir아무것도 하지 않았습니다.훌륭합니다. 효과가 있었습니다!

이 결과는 사실과 완전히 같지 않습니다.--hard재설정, 왜냐하면 참이기 때문입니다.--hard해도 재정이 설않음으로 새 .git commit은 단순히 체크아웃된 지점을 가리키도록 합니다.commit_hash그러나 이와 같은 몇 개의 파일이나 경로만 "하드 리셋"할 때 다른 파일이나 경로를 가리키기 위해 분기 포인터를 이동할 수는 없습니다.commit_hash따라서 위와 같이 이러한 "추가되지 않음" 또는 "추가되지 않음" 변경 사항이 포함된 새 커밋을 추가하는 것 외에는 이 명령에 대한 합리적인 동작을 구현할 수 있는 방법이 없습니다.

이러한 통찰력이 또한 이유일 수 있습니다.git으로 기적으않다습니를 --hard; 경별재옵션; 아도그것 입니다.--hard커밋을 , 이 커밋은 인 커밋과 다릅니다.--hard새 커밋을 추가하지 않고 지정된 커밋으로 분기 포인터를 이동하도록 "재설정"하는 동작입니다.

그것은 근본적으로 이유를 설명하지 못합니다.git적어도 허락하지 않을 것입니다--soft하지만 Git는 경로별로 재설정됩니다. 제가 보기에는 그것이 더 표준적인 것 같습니다.

배경지식

git 용어

당신이 읽고 있는 것처럼.man git reset페이지, 당신은 몇 가지 Git 용어를 이해해야 합니다.

  1. 작업 트리 = 로컬 파일 시스템; 이것은 터미널 또는 GUI 파일 관리자에서 파일 시스템을 탐색할 때 나타나는 상태의 파일 및 폴더를 나타냅니다.nemo,nautilus또는thunar.
  2. <tree-ish> 또는
  3. 인덱스 = 실행 시 녹색으로 표시되는 항목git status이것들이 모든 변화입니다.git add 않았습니다ed("staged"), 그나아커않았습니다지밋되직.을 할 때git add some_file 당고신 "집입"입니다.some_file변경 사항을 인덱스로 이동하여 확인할 수 있습니다.이제 말할 수 있습니다.some_file는 "추가됨", "추가됨" 또는 "인덱스 내"(모두 동일)입니다.

2. man git reset페이지들

이러한 솔루션을 읽고 있는 동안 통찰력이 뛰어나고 유용합니다.man git reset상태(추가되지 않음):

git reset <paths>는 의반니다의 입니다.git add <paths>.

다른말하면로,하면,git reset commit_hash -- some_file_or_dir의 변경 내용을 "추가 취소"하거나 의 반대 변경 내용을 추가할 수 있습니다(변경 내용을 취소할 수 있음).some_file_or_dir branch에 된 commit_hash▁를 설정하는 동안.HEAD가자면키를 commit_hash또는 그것이 가리키는 것처럼.commit_hash디렉토리에 (하여 "" " " " " " " " (", " " " " " " " ")를 만듭니다.some_file_or_dir작업 트리에서 처럼 보입니다.some_file_or_dircommit_hash.

한또에서는,gitlingo, "작업 트리"는 "당신의 로컬 파일 시스템"을 의미하고, "인덱스" 또는 "인덱스 파일"은 "당신의 로컬 파일 시스템"을 의미합니다.git add또는 그들을 '무대'합니다."을 할 때git status녹색으로 표시된 모든 파일은 "인덱스" 또는 "인덱스" 또는 "인덱스 파일"(동일한 파일)입니다.(출처:Git에서 HEAD, 작업 트리 인덱스의 차이점은 무엇입니까?)

자, 그것을 염두에 두고, 여기 몇 가지 중요한 부분이 있습니다.man git reset:

git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

형태 [헤드 (세번 양 [위 표 된 에 양 식 [시 헤 분 드 기 현 재 서 에 식 째 에 헤 드 ( ▁in ▁head ▁the 기 위 분 the ▁set ▁( ], 세 ▁above ▁the ▁shown ▁branchHEAD에서 )까지<commit>선택적으로 일치하도록 인덱스 및 작업 트리를 수정합니다.<tree-ish>/<commit>은 " " "입니다.HEAD온갖 형태로

그리고:

git reset [-q] [<tree-ish>] [--] <paths>...
    This form resets the index entries for all <paths> to
    their state at <tree-ish>. (It does not affect the working
    tree or the current branch.)
    
    **This means that `git reset <paths>` is the opposite of `git
    add <paths>`.**
      
    After running git reset <paths> to update the index entry,
    you can use git-checkout(1) to check the contents out of
    the index to the working tree. Alternatively, using git-
    checkout(1) and specifying a commit, you can copy the
    contents of a path out of a commit to the index and to the
    working tree in one go.

그리고:

git reset [<mode>] [<commit>]
    This form resets the current branch head to <commit> and
    possibly updates the index (resetting it to the tree of
    <commit>) and the working tree depending on <mode>. If
    <mode> is omitted, defaults to "--mixed". The <mode> must
    be one of the following:
     
    --soft
        Does not touch the index file or the working tree at
        all (but resets the head to <commit>, just like all
        modes do). This leaves all your changed files "Changes
        to be committed", as git status would put it.
     
    --mixed
        Resets the index but not the working tree (i.e., the
        changed files are preserved but not marked for commit)
        and reports what has not been updated. This is the
        default action.
     
        If -N is specified, removed paths are marked as
        intent-to-add (see git-add(1)).
     
    --hard
        Resets the index and working tree. Any changes to
        tracked files in the working tree since <commit> are
        discarded.

당신은 또한 그것에 익숙해야 합니다.man git checkout-index페이지입니다.

"index"에는 추가되거나 "staged"된 모든 파일이 포함됩니다(실행 시 녹색으로 표시됨)git status) 및 "작업 트리"는 실제 로컬 파일 시스템을 나타냅니다(실행 시 빨간색으로 표시된 변경 사항도 포함).git status).

가장 기본적인 수준에서는 다음과 같은 작업을 수행합니다.

man git checkout-index:

NAME
       git-checkout-index - Copy files from the index to the working tree

그리고:

-f, --force
    forces overwrite of existing files

-a, --all
    checks out all files in the index. Cannot be used together with
    explicit filenames.

참조:

  1. [내 대답--직접적으로 적용 가능하며, 위의 전체 답변을 작성하는 데 필요한 선행 답변!]git를 사용하여 작업 트리(로컬 파일 시스템 상태)를 인덱스 상태("준비된" 파일)로 재설정하려면 어떻게 해야 합니까?
  2. 현재 Git 작업 트리에서 로컬(추적되지 않은) 파일을 제거하는 방법
  3. Git의 단계별 변경을 취소하려면 어떻게 해야 합니까?
  4. Git에서 HEAD, 작업 트리와 인덱스의 차이점은 무엇입니까?

관련:

  1. [내 대답] 다른 지점에서 파일 하나만 가져오려면 어떻게 해야 합니까?

설명.

설명서에는 세 가지 호출 방법이 나와 있습니다.

  • 2개는 파일 단위입니다.는 작업 트리에 영향을 미치지 않지만 다음과 같이 지정된 인덱스의 파일에서만 작동합니다.<paths>:

    • git reset [-q] [<tree-ish>] [--] <paths>..
    • git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
  • 1은 커밋 방식입니다.참조된 모든 파일에서 작동합니다.<commit>작업 트리에 영향을 미칠 수 있습니다.

    • git reset [<mode>] [<commit>]

지정된 파일에서만 작동하고 작업 트리에 영향을 주는 호출 모드는 없습니다.

해결 방법

둘 다 원하는 경우:

  • 파일의 인덱스/캐시 버전 재설정
  • 파일 체크아웃(즉, 작업 트리를 인덱스와 일치시키고 버전을 커밋)

Git 구성 파일에서 다음 별칭을 사용할 수 있습니다.

[alias]
  reco   = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #"  # Avoid: "fatal: Cannot do hard reset with paths."

그런 다음 다음 중 하나를 수행할 수 있습니다.

$ git reco <paths>

$ git reco <branch/commit> <paths>

$ git reco -- <paths>

의 경우) reco:re& & 트세&c제기랄out)

git reset --soft HEAD~1 파일 이름은 커밋을 실행 취소하지만 변경 사항은 로컬에 남아 있습니다.파일 이름은 -- 커밋된 모든 파일에 대해 가능합니다.

언급URL : https://stackoverflow.com/questions/11200839/why-git-cant-do-hard-soft-resets-by-path

반응형