program tip

일반 영어로 "git reset"은 무엇을합니까?

radiobox 2020. 10. 2. 21:57
반응형

일반 영어로 "git reset"은 무엇을합니까?


대한 미묘함을 설명하는 흥미로운 게시물 을 보았습니다 git reset.

불행히도 더 많이 읽을수록 완전히 이해하지 못하는 것처럼 보입니다. 저는 SVN 배경에서 왔으며 Git은 완전히 새로운 패러다임입니다. 나는 쉽게 수은을 얻었지만 Git은 훨씬 더 기술적입니다.

git reset에 가깝다고 생각 hg revert하지만 차이점이있는 것 같습니다.

그래서 정확히 무엇을 git reset합니까? 다음에 대한 자세한 설명을 포함하십시오.

  • 옵션 --hard, --soft--merge;
  • 당신이 사용하는 이상한 표기 HEADHEAD^HEAD~1;
  • 구체적인 사용 사례 및 작업 흐름
  • 작업 사본, HEAD글로벌 스트레스 수준 에 미치는 영향 .

일반적으로 git reset의 기능은 현재 분기를 가져 와서 다른 곳을 가리 키도록 재설정하고 가능하면 인덱스와 작업 트리를 함께 가져 오는 것입니다. 보다 구체적으로 마스터 브랜치 (현재 체크 아웃)가 다음과 같다면 :

- A - B - C (HEAD, master)

마스터가 C가 아닌 B를 가리 키기를 원한다는 것을 알고 있습니다 git reset B.

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

Digression : 이것은 체크 아웃과 다릅니다. 실행 git checkout B하면 다음을 얻을 수 있습니다.

- A - B (HEAD) - C (master)

분리 된 HEAD 상태가되었습니다. HEAD, 작업 트리, 색인이 모두 일치 B하지만 마스터 브랜치는에 남아 있습니다 C. D이 시점에서 새 커밋 을 수행하면 다음과 같은 결과를 얻을 수 있습니다. 이는 아마도 원하는 것이 아닐 것입니다.

- A - B - C (master)
       \
        D (HEAD)

reset은 커밋을 만드는 것이 아니라 다른 커밋을 가리 키도록 분기 (커밋에 대한 포인터) 만 업데이트한다는 점을 기억하십시오. 나머지는 인덱스 및 작업 트리에 어떤 일이 발생하는지에 대한 세부 정보입니다.

사용 사례

git reset다음 섹션의 다양한 옵션에 대한 설명에서 많은 주요 사용 사례를 다룹니다. 정말 다양한 용도로 사용할 수 있습니다. 공통 스레드는 모두 분기, 인덱스 및 / 또는 작업 트리를 재설정하여 주어진 커밋을 가리 키거나 일치시키는 것을 포함한다는 것입니다.

주의 사항

  • --hard정말 일을 잃을 수 있습니다. 작업 트리를 수정합니다.

  • git reset [options] commit커밋을 (일종의) 잃을 수 있습니다. 위의 장난감 예제에서 commit을 잃었습니다 C. 그것은 REPO에 아직, 당신은보고 찾을 수 있습니다 git reflog show HEAD또는 git reflog show master, 그러나 더 이상 실제로 어떤 지점에서 액세스 할 수 없습니다.

  • Git은 30 일 후에 이러한 커밋을 영구적으로 삭제하지만 그때까지는 분기를 다시 가리키면 C를 복구 할 수 있습니다 ( git checkout C; git branch <new branch name>).

인수

man 페이지를 의역하면 가장 일반적인 사용법은 git reset [<commit>] [paths...]주어진 커밋에서 주어진 경로를 상태로 재설정하는 형식 입니다. 경로가 제공되지 않으면 전체 트리가 재설정되고 커밋이 제공되지 않으면 HEAD (현재 커밋)가됩니다. 이것은 git 명령 (예 : 정확한 의미는 다르지만 checkout, diff, log)에서 공통된 패턴이므로 그리 놀라운 것은 아닙니다.

예를 들어, git reset other-branch path/to/foopath / to / foo의 모든 항목을 other-branch의 상태로 git reset -- .재설정하고 현재 디렉토리를 HEAD의 상태로 git reset재설정 하고 단순하게 모든 항목을 HEAD의 상태로 재설정합니다.

주요 작업 트리 및 색인 옵션

재설정하는 동안 작업 트리 및 인덱스에 발생하는 작업을 제어하는 ​​네 가지 주요 옵션이 있습니다.

인덱스는 git의 "스테이징 영역"이라는 것을 기억하십시오 git add. 커밋을 준비 할 때 작업이 진행되는 곳 입니다.

  • --hard모든 것을 재설정 한 커밋과 일치시킵니다. 아마도 이것은 이해하기 가장 쉬운 방법입니다. 모든 로컬 변경 사항이 방해받습니다. 하나 개의 기본 사용은 당신의 일을 멀리 불고 있지만 커밋 전환되지 않습니다 git reset --hard수단 git reset --hard HEAD, 즉 분기를 변경하지 않지만 모든 로컬 변경 사항을 제거. 다른 하나는 단순히 한 위치에서 다른 위치로 분기를 이동하고 인덱스 / 작업 트리를 동기화 상태로 유지하는 것입니다. 이것은 작업 트리를 수정하기 때문에 실제로 작업을 잃게 만들 수 있습니다. 실행하기 전에 로컬 작업을 버리고 싶은지 매우 확인하십시오 reset --hard.

  • --mixed기본값입니다. 즉을 git reset의미 git reset --mixed합니다. 색인을 재설정하지만 작업 트리는 재설정하지 않습니다. 즉, 모든 파일이 그대로 유지되지만 원래 커밋과 재설정 한 커밋 간의 차이점은 git 상태의 로컬 수정 (또는 추적되지 않은 파일)으로 표시됩니다. 당신이 나쁜 커밋을했다는 것을 깨달았지만 당신이 한 모든 작업을 유지하고 싶을 때 이것을 사용하여 그것을 고치고 다시 커밋 할 수 있습니다. 커밋하려면 인덱스에 파일을 다시 추가해야합니다 ( git add ...).

  • --soft색인 이나 작업 트리를 건드리지 않습니다 . 모든 파일은 그대로 유지 --mixed되지만 모든 변경 사항은 changes to be committedgit 상태 로 표시됩니다 (예 : 커밋 준비 중 체크인). 당신이 나쁜 커밋을했다는 것을 깨달았을 때 이것을 사용하세요.하지만 작업은 모두 훌륭합니다. 당신이해야 할 일은 다르게 재 커밋하는 것뿐입니다. 인덱스는 변경되지 않으므로 원하는 경우 즉시 커밋 할 수 있습니다. 결과 커밋에는 재설정하기 전과 동일한 내용이 모두 포함됩니다.

  • --merge was added recently, and is intended to help you abort a failed merge. This is necessary because git merge will actually let you attempt a merge with a dirty work tree (one with local modifications) as long as those modifications are in files unaffected by the merge. git reset --merge resets the index (like --mixed - all changes show up as local modifications), and resets the files affected by the merge, but leaves the others alone. This will hopefully restore everything to how it was before the bad merge. You'll usually use it as git reset --merge (meaning git reset --merge HEAD) because you only want to reset away the merge, not actually move the branch. (HEAD hasn't been updated yet, since the merge failed)

    To be more concrete, suppose you've modified files A and B, and you attempt to merge in a branch which modified files C and D. The merge fails for some reason, and you decide to abort it. You use git reset --merge. It brings C and D back to how they were in HEAD, but leaves your modifications to A and B alone, since they weren't part of the attempted merge.

Want to know more?

I do think man git reset is really quite good for this - perhaps you do need a bit of a sense of the way git works for them to really sink in though. In particular, if you take the time to carefully read them, those tables detailing states of files in index and work tree for all the various options and cases are very very helpful. (But yes, they're very dense - they're conveying an awful lot of the above information in a very concise form.)

Strange notation

The "strange notation" (HEAD^ and HEAD~1) you mention is simply a shorthand for specifying commits, without having to use a hash name like 3ebe3f6. It's fully documented in the "specifying revisions" section of the man page for git-rev-parse, with lots of examples and related syntax. The caret and the tilde actually mean different things:

  • HEAD~ is short for HEAD~1 and means the commit's first parent. HEAD~2 means the commit's first parent's first parent. Think of HEAD~n as "n commits before HEAD" or "the nth generation ancestor of HEAD".
  • HEAD^ (or HEAD^1) also means the commit's first parent. HEAD^2 means the commit's second parent. Remember, a normal merge commit has two parents - the first parent is the merged-into commit, and the second parent is the commit that was merged. In general, merges can actually have arbitrarily many parents (octopus merges).
  • The ^ and ~ operators can be strung together, as in HEAD~3^2, the second parent of the third-generation ancestor of HEAD, HEAD^^2, the second parent of the first parent of HEAD, or even HEAD^^^, which is equivalent to HEAD~3.

caret and tilde


Remember that in git you have:

  • the HEAD pointer, which tells you what commit you're working on
  • the working tree, which represents the state of the files on your system
  • the staging area (also called the index), which "stages" changes so that they can later be committed together

Please include detailed explanations about:

--hard, --soft and --merge;

In increasing order of dangerous-ness:

  • --soft moves HEAD but doesn't touch the staging area or the working tree.
  • --mixed moves HEAD and updates the staging area, but not the working tree.
  • --merge moves HEAD, resets the staging area, and tries to move all the changes in your working tree into the new working tree.
  • --hard moves HEAD and adjusts your staging area and working tree to the new HEAD, throwing away everything.

concrete use cases and workflows;

  • Use --soft when you want to move to another commit and patch things up without "losing your place". It's pretty rare that you need this.

--

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

--

  • Use --mixed (which is the default) when you want to see what things look like at another commit, but you don't want to lose any changes you already have.

  • Use --merge when you want to move to a new spot but incorporate the changes you already have into that the working tree.

  • Use --hard to wipe everything out and start a fresh slate at the new commit.


The post Reset Demystified in the blog Pro Git gives a very no-brainer explanation on git reset and git checkout.

After all the helpful discussion at the top of that post, the author reduces the rules to the following simple three steps:

That is basically it. The reset command overwrites these three trees in a specific order, stopping when you tell it to.

  1. Move whatever branch HEAD points to (stop if --soft)
  2. THEN, make the Index look like that (stop here unless --hard)
  3. THEN, make the Working Directory look like that

There are also --merge and --keep options, but I would rather keep things simpler for now - that will be for another article.


When you commit something to git you first have to stage (add to the index) your changes. This means you have to git add all the files you want to have included in this commit before git considers them part of the commit. Let's first have a look over the image of a git repo: enter image description here

so, its simple now. We have to work in working directory, creating files, directories and all. These changes are untracked changes. To make them tracked, we need to add them to git index by using git add command. Once they are added to git index. We can now commit these changes, if we want to push it to git repository.

But suddenly we came to know while commiting that we have one extra file which we added in index is not required to push in git repository. It means we don't want that file in index. Now the question is how to remove that file from git index, Since we used git add to put them in the index it would be logical to use git rm? Wrong! git rm will simply delete the file and add the deletion to the index. So what to do now:

Use:-

git reset

It Clears your index, leaves your working directory untouched. (simply unstaging everything).

It can be used with number of options with it. There are three main options to use with git reset: --hard, --soft and --mixed. These affect what get’s reset in addition to the HEAD pointer when you reset.

First, --hard resets everything. Your current directory would be exactly as it would if you had been following that branch all along. The working directory and the index are changed to that commit. This is the version that I use most often. git reset --hard is something like svn revert .

Next, the complete opposite, —soft, does not reset the working tree nor the index. It only moves the HEAD pointer. This leaves your current state with any changes different than the commit you are switching to in place in your directory, and “staged” for committing. If you make a commit locally but haven’t pushed the commit to the git server, you can reset to the previous commit, and recommit with a good commit message.

Finally, --mixed resets the index, but not the working tree. So the changes are all still there, but are “unstaged” and would need to be git add’ed or git commit -a. we use this sometimes if we committed more than we meant to with git commit -a, we can back out the commit with git reset --mixed, add the things that we want to commit and just commit those.

Difference between git revert and git reset :-


In simple words, git reset is a command to "fix-uncommited mistakes" and git revert is a command to "fix-commited mistake".

It means if we have made some error in some change and commited and pushed the same to git repo, then git revert is the solution. And if in case we have identified the same error before pushing/commiting, we can use git reset to fix the issue.

I hope it will help you to get rid of your confusion.


TL;DR

git reset resets Staging to the last commit. Use --hard to also reset files in your Working directory to the last commit.

LONGER VERSION

But that's obviously simplistic hence the many rather verbose answers. It made more sense for me to read up on git reset in the context of undoing changes. E.g. see this:

If git revert is a “safe” way to undo changes, you can think of git reset as the dangerous method. When you undo with git reset(and the commits are no longer referenced by any ref or the reflog), there is no way to retrieve the original copy—it is a permanent undo. Care must be taken when using this tool, as it’s one of the only Git commands that has the potential to lose your work.

From https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

and this

On the commit-level, resetting is a way to move the tip of a branch to a different commit. This can be used to remove commits from the current branch.

From https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations


Please be aware, this is a simplified explanation intended as a first step in seeking to understand this complex functionality.

May be helpful for visual learners who want to visualise what their project state looks like after each of these commands:


For those who use Terminal with colour turned on (git config --global color.ui auto):

git reset --soft A and you will see B and C's stuff in green (staged and ready to commit)

git reset --mixed A (or git reset A) and you will see B and C's stuff in red (unstaged and ready to be staged (green) and then committed)

git reset --hard A and you will no longer see B and C's changes anywhere (will be as if they never existed)


Or for those who use a GUI program like 'Tower' or 'SourceTree'

git reset --soft A and you will see B and C's stuff in the 'staged files' area ready to commit

git reset --mixed A (or git reset A) and you will see B and C's stuff in the 'unstaged files' area ready to be moved to staged and then committed

git reset --hard A and you will no longer see B and C's changes anywhere (will be as if they never existed)


Checkout points the head at a specific commit.

Reset points a branch at a specific commit. (A branch is a pointer to a commit.)

Incidentally, if your head doesn’t point to a commit that’s also pointed to by a branch then you have a detached head. (turned out to be wrong. See comments...)

참고URL : https://stackoverflow.com/questions/2530060/in-plain-english-what-does-git-reset-do

반응형