파일 체크 아웃없이 Git 분기 전환


100

Git에서 모든 파일을 체크 아웃하지 않고 다른 브랜치로 전환 할 수 있습니까?

브랜치를 전환 한 후 모든 파일을 삭제하고 재생성하고 커밋하고 다시 전환해야합니다. 따라서 파일을 체크 아웃하는 것은 시간 낭비 일뿐입니다 (약 14,000 개의 파일이 있으며 긴 작업입니다).

모든 것을 명확하게하려면 :

문서 를 GitHub 에 업로드하려면이 모든 것이 필요합니다 .

gh-pages 브랜치 가있는 저장소가 있습니다. 문서를 로컬로 다시 빌드 할 때 저장소 디렉터리에 복사하고 커밋하고 GitHub에 푸시합니다. 그러나 나는 로컬에 두 개의 문서 사본을 가지고 있었기 때문에 행복하지 않았습니다. 그리고 빈 가지를 만들고 커밋 한 후 빈으로 전환하고 파일을 삭제하기로 결정했습니다. 그러나 다시 전환하는 것은 긴 작업이므로이 질문을했습니다.

gh-pages 브랜치 에 남겨두고 파일을 삭제할 수 있다는 것을 알고 있지만 더러운 작업 트리를 좋아하지 않습니다.


당신에게 "길다"는 것은 얼마나됩니까? 어떤 플랫폼에서 작업하고 있습니까? NFS 또는 기타 파일 공유와 같은 네트워크를 통해 작업하고 있습니까?
Greg Hewgill

이 연습의 목적은 무엇입니까? 두 개의 브랜치, 세부 커밋이있는 브랜치, 두 번째는 주요 변경 사항 (거친 그레인 드) 만 기록 하시겠습니까?
Jakub Narębski

작업 복사본의 임시 (또는 영구?) 복제본을 만드는 것이 더 저렴할 수 있습니다. 내 관련 답변 은 이것이 주 저장소의 하위 디렉토리로도 어떻게 작동하는지 보여줍니다.
krlmlr

답변:


106

예, 할 수 있습니다.

git symbolic-ref HEAD refs/heads/otherbranch

이 브랜치에서 커밋해야하는 경우 인덱스도 재설정해야합니다. 그렇지 않으면 마지막으로 체크 아웃 한 브랜치를 기반으로 무언가를 커밋하게됩니다.

git reset

1
분기 대신 참조를 가리 키려면 echo "ebff34ffb665de0694872dceabe0edeaf50ec5a9" > .git/HEAD뒤에 사용하십시오 git reset.
cadorn

1
HEAD 파일에 직접 쓰는 것은 덜 신뢰할 수 있습니다. 만약 당신이 subdir에 있다면? 분리 된 헤드 (헤드가 SHA1을 직접 가리키고 있음)의 경우 다음을 시도하십시오. git update-ref HEAD refs/heads/otherbranch
Alexander Bird

2
현재 브랜치에서 새로운 브랜치로 체크 아웃하고 싶다면 다른 방법은 1입니다. git stash2. git checkout -b otherBranch3.git stash pop
Winny

@AlexanderBird : git update-ref유용하지만 현재 분기의 끝도 이동합니다.
tomekwi

47

기본 git 명령 만 사용 :

이 답변은 Charles의 답변보다 약간 길지만, 제가 이해할 수 있고 기억할 수있는 기본적인 git 명령으로 만 구성되어 있으므로 계속 검색 할 필요가 없습니다.

현재 위치를 표시 (필요한 경우 먼저 커밋) :

git checkout -b temp

작업 디렉토리를 변경하지 않고 마커를 다른 분기로 재설정 (이동)합니다.

git reset <branch where you want to go>

이제 임시 및 기타 분기가 동일한 커밋을 가리키고 작업 디렉토리는 변경되지 않습니다.

git checkout <branch where you want to go>

HEAD가 이미 동일한 커밋을 가리키고 있으므로 작업 디렉토리가 건드리지 않습니다.

git branch -d temp

이러한 명령은 모든 그래픽 클라이언트에서도 쉽게 사용할 수 있습니다.


7
내가 선호하는 git reset --soft <branch where you want to go>인덱스를 업데이트 피하기 위해
JoelFan

7
나는 git 배관 명령을 피하고 도자기 명령을 선호하는 당신의 전략에 동의합니다.
user64141

26

v2.24에서는 git switch금고 같은 것 git checkout입니다.
따라서 아래 별칭 git hop
"작업 트리를 변경하지 않고 분기에서 홉"으로 이름 을 변경했습니다.

독자의 이익을 위해 :

Charles Bailey의 솔루션 이 옳다고 생각하지만 이 솔루션은 로컬 브랜치가 아닌 것으로 전환 할 때 조정이 필요합니다. 또한 이해하기 쉬운 일반 명령으로 수행하는 방법이 있어야합니다. 내가 생각해 낸 것은 다음과 같습니다.

git checkout --detach
git reset --soft commitish
git checkout commitish

설명 :

  • git checkout --detachgit checkout HEAD^{}현재 분기를 뒤로하고 "분리 된 헤드 상태" 가되는 것과 동일 합니다. 따라서 다음 수정은 HEAD더 이상 분기에 영향 을 주지 않습니다. 분리 HEAD는 작업 트리 나 색인에 영향을주지 않습니다.
  • git reset --soft commitish그런 다음 HEAD주어진의 SHA 로 이동 합니다 commitish. 색인도 업데이트하려면 그대로 두십시오 --soft. 그러나 그렇게하지 않는 것이 좋습니다. 이것은 다시 작업 트리를 건드리지 --soft않고 ( ) 인덱스를 건드리지 않습니다.
  • git checkout commitish그런 다음 HEAD주어진 commitish(분기)에 다시 연결 합니다. ( commitishSHA 라면 아무 일도 일어나지 않습니다.) 이것 역시 인덱스 나 워크 트리에 영향을주지 않습니다.

이 솔루션은 커밋을 참조하는 모든 것을 허용하므로 일부 git별칭에 이상적입니다 . 그만큼rev-parse아래는 오타 실수 (방법은 더 복잡 할 것이다 오류 복구) 분리 된 헤드 상태로 전환하지 않도록해야합니다 단지 테스트, 체인 아무것도 휴식입니다.

이로 인해 다음 git hop treeish별칭 이 생성됩니다 .

git config --global alias.hop '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f'

참고로 내 git별칭 목록에서 찾을 수 있습니다 .


$@대신 사용하고 싶지 $*않습니까? 차이점은 내부에 공백이있는 확장 인용 인수가없는 $ @입니다.
kyb

1
@kyb 함수 트릭은 다른 SO 답변에서 도난당했습니다 . 그리고 $@여기서는 확실히 의미가 없습니다. $*대신에 사용 $1되도록, git switch -f b동일하게하기로 git switch '-f b'하는 에러이어야한다. 이렇게하면 다음과 같은 오류 처리를 !f() { [ 1 = $# ] || { echo 'WTF!'; return 1; }; ..
Tino

아주 좋은 솔루션입니다. 특히 원격 지점에 사용할 수 있다는 점!
Nils-o-mat

14

두 개의 작업 디렉토리 (두 개의 작업 영역)와 하나의 저장소 또는 두 개의 저장소를 갖는 것이 더 나은 솔루션이 아닐까요?

자식 새로운-WORKDIR의 에서 도구 contrib/이 당신을 도울 수있는 부분은.


git-new-workdir은 git의 작업 트리 명령과 동일합니까? 전체 저장소를 복제 할 필요없이 다른 폴더로 분기를 체크 아웃 할 때 작업 트리를 사용합니다.
Ryuu

git-new-worktree스크립트 선행은 git worktree부속 명령; 이 명령은 답변이 작성되었을 때 사용할 수 없었습니다. 예를 들어 스크립트에는 symlink 지원이 필요합니다. IMHO 기본 지원을 사용하는 것이 좋습니다.
Jakub Narębski

8

배관 명령을 찾고 계신 것 같습니다 git read-tree. 이렇게하면 색인이 업데이트되지만 작업 디렉토리의 파일은 업데이트되지 않습니다. 예를 들어 다음과 같이 branch읽을 분기의 이름을 가정 합니다.

자식 읽기 트리 분기

방금 읽은 브랜치에 커밋하려면 다음을 수행해야합니다.

git symbolic-ref HEAD refs / heads / branch

아니요 분기 만 전환하면됩니다. 다른 변경 사항은 없습니다. 따라서 symbolic-ref가 충분합니다
tig

read-tree오류를 생성합니다 : 아직 fatal: Not a valid object name branch없는 경우git switch branch
Andry

7

다른 브랜치 이름으로 HEAD 파일을 덮어 쓸 수 있습니다.

echo "ref : refs / heads / MyOtherBranch"> .git / HEAD


13
이 작업을 수행하려면 symbolic-ref 명령을 사용하는 것이 좋습니다. git symbolic-ref HEAD refs/heads/MyOtherBranch kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html
Greg Hewgill 2009-08-15

@GregHewgill, 이것은 HEAD를 커밋 해시로 이동하는 유일한 방법입니다. 당신은 그것을 할 수 있습니까 git symbolic-ref?
tomekwi

0

파일이 너무 많으면 각 브랜치에 하나씩 두 개의 저장소를 유지하는 것이 가장 좋습니다. 필요에 따라 변경 사항을 앞뒤로 가져올 수 있습니다. 이것은 git로 괴혈병 트릭을 시도하는 것보다 덜 놀랍습니다.


git-new-worktree대신 사용할 수 있습니다 (에서 contrib/)
Jakub Narębski 2009-08-16

나는 종종 비슷한 일을했다. 이것은 초보자로서 "무서운 자식 작업"을하기 전에 내 로컬 디렉토리를 복사하는 것이다 (분기 변경 등). 나는 당신이 당신의 git-fu에 자신감을 가질 때까지 사람들이 그 길을 가도록 권하고, 가능하면 그것에서 벗어나도록 격려하고 싶습니다. 두 개의 별개의 저장소를 유지하는 것은 괜찮지 만 복잡한 계층을 추가하고 git의 많은 유용한 기능 (병합, 체리 따기 등)을 활용할 수 없습니다.
David

0

원격 분기가 가리키는 위치를 단순히 변경하려는 경우 로컬 복사본을 건드리지 않고 "git push"를 사용하여 수행 할 수 있습니다.

http://kernel.org/pub/software/scm/git/docs/git-push.html

<refspec> 매개 변수의 형식은 선택적 더하기 +, 소스 참조 <src>, 콜론 :, 대상 참조 <dst> 순입니다. 원격 저장소의 <dst> 참조를 업데이트 할 <src> 개체를 지정하는 데 사용됩니다.

예를 들어, c5f7eba를 커밋하도록 foo를 업데이트하려면 다음을 수행하십시오.

git push origin c5f7eba:foo

그것이 당신이 추구했던 것인지 아닌지 확실하지 않습니다.


질문은 이미 답을 얻었습니다 : stackoverflow.com/questions/1282639/…
tig

0

당신은 사용할 수 있습니다

      1. git checkout -f <new-branch>
      2. git cherry-pick -x <previous-branch-commit-id>

previous-branch-commit-id는 이전 데이터를 복사하려는 커밋입니다.


0

또는 패치 파일을 사용하여 다른 분기에서 마스터로 패치하십시오.

git diff otherbranch master > ~/tmp/otherbranch.diff
git checkout master
git apply ~/tmp/otherbranch.diff

-1

분기 A에 있고 싶지만 분기 B의 파일을 사용하고 싶다고 말하십시오.

git log를 사용하여 분기 A의 현재 커밋 참조를 찾습니다 (예 : "99ce9a2").

git checkout A
git reset --hard B
git reset 99ce9a2

이제 B에 해당하는 폴더 구조가있는 분기 A에 있어야합니다.이 폴더 구조는 단계되지 않은 변경 사항으로 표시됩니다 (A 내역은 변경되지 않음).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.