소개
Git 의 cherry-pick 기능은 특정 커밋을 한 브랜치에서 다른 브랜치로 적용할 수 있게 해줍니다. 강력한 기능이지만, 오류나 충돌로 인해 cherry-pick 작업을 되돌려야 할 때가 있습니다. 이 랩에서는 cherry-pick 을 수행한 다음, 필요할 때 이를 취소하는 다양한 방법을 배우게 됩니다. 이 랩을 마치면 cherry-pick 작업에 대한 실질적인 경험과 일반적인 문제로부터 복구하는 기술을 갖추게 될 것입니다.
Git 의 cherry-pick 기능은 특정 커밋을 한 브랜치에서 다른 브랜치로 적용할 수 있게 해줍니다. 강력한 기능이지만, 오류나 충돌로 인해 cherry-pick 작업을 되돌려야 할 때가 있습니다. 이 랩에서는 cherry-pick 을 수행한 다음, 필요할 때 이를 취소하는 다양한 방법을 배우게 됩니다. 이 랩을 마치면 cherry-pick 작업에 대한 실질적인 경험과 일반적인 문제로부터 복구하는 기술을 갖추게 될 것입니다.
이 단계에서는 cherry-pick 작업을 연습하기 위해 테스트 Git 레포지토리를 생성합니다. 이를 통해 다양한 Git 명령을 안전하게 실험할 수 있는 환경을 제공합니다.
테스트 레포지토리를 위한 새 디렉토리를 생성하고 이를 Git 레포지토리로 초기화하는 것으로 시작해 보겠습니다.
mkdir -p ~/project/cherry-pick-lab
cd ~/project/cherry-pick-lab
git init
다음과 유사한 출력을 볼 수 있습니다.
Initialized empty Git repository in /home/labex/project/cherry-pick-lab/.git/
커밋을 하기 전에 Git 에 대한 사용자 이름과 이메일을 설정해야 합니다.
git config --local user.name "LabEx User"
git config --local user.email "labex@example.com"
메인 브랜치에서 몇 가지 초기 커밋을 생성해 보겠습니다.
## 첫 번째 파일 생성 및 커밋
echo "## Cherry Pick Lab" > README.md
git add README.md
git commit -m "Initial commit with README"
## 두 번째 파일 생성 및 커밋
echo "console.log('Hello, world!');" > app.js
git add app.js
git commit -m "Add main application file"
모든 것이 올바르게 설정되었는지 확인하기 위해 커밋 기록을 확인해 보겠습니다.
git log --oneline
다음과 유사한 출력을 볼 수 있습니다.
abcd123 (HEAD -> main) Add main application file
efgh456 Initial commit with README
실제 커밋 해시는 시스템에 따라 다릅니다. 나중에 사용할 "Add main application file"의 커밋 해시를 기록해 두십시오.
이제 몇 가지 추가 변경 사항을 만들 기능 브랜치를 생성해 보겠습니다.
git checkout -b feature-branch
다음과 유사한 출력을 볼 수 있습니다.
Switched to a new branch 'feature-branch'
이제 이 기능 브랜치에 몇 가지 커밋을 추가해 보겠습니다.
## 새로운 기능 파일 생성 및 커밋
echo "function newFeature() { return 'awesome'; }" > feature.js
git add feature.js
git commit -m "Add new feature function"
## README 파일 수정
echo -e "## Cherry Pick Lab\n\nThis repo demonstrates git cherry-pick operations." > README.md
git add README.md
git commit -m "Update README with project description"
이제 두 개의 커밋이 있는 메인 브랜치와 두 개의 추가 커밋이 있는 기능 브랜치가 있습니다. 다음 단계에서는 cherry-pick 을 사용하여 기능 브랜치 커밋 중 하나를 메인 브랜치에 적용합니다.
이 단계에서는 cherry-pick 명령을 사용하여 특정 커밋을 한 브랜치에서 다른 브랜치로 적용하는 방법을 배웁니다. 이는 한 브랜치의 변경 사항을 선택적으로 다른 브랜치에 통합하려는 경우에 유용합니다.
Git 의 Cherry-picking 을 사용하면 한 브랜치에서 특정 커밋을 선택하여 다른 브랜치에 적용할 수 있습니다. 일반적으로 여러 커밋을 적용하는 병합 (merging) 또는 리베이스 (rebasing) 와 달리, cherry-picking 은 한 번에 하나의 커밋만 적용합니다.
먼저, 기능 브랜치의 커밋을 적용하려는 메인 브랜치로 다시 전환해 보겠습니다.
git checkout main
전환을 확인하는 출력을 볼 수 있습니다.
Switched to branch 'main'
Cherry-picking 을 하기 전에, 메인 브랜치에 적용할 수 있는 기능 브랜치의 커밋을 살펴보겠습니다.
git log feature-branch --oneline
이렇게 하면 메인 브랜치와 공유되는 커밋을 포함하여 기능 브랜치의 모든 커밋이 표시됩니다. 다음과 유사한 출력을 볼 수 있습니다.
1234abc Update README with project description
5678def Add new feature function
abcd123 Add main application file
efgh456 Initial commit with README
"Add new feature function"의 커밋 해시를 기록해 두십시오 (이 예에서는 5678def 입니다). 다음 단계에서 이 해시를 사용합니다.
이제 "Add new feature function" 커밋을 기능 브랜치에서 메인 브랜치로 cherry-pick 해보겠습니다.
git cherry-pick [COMMIT_HASH]
[COMMIT_HASH]를 이전에 기록한 실제 해시로 바꿉니다. 예를 들어:
git cherry-pick 5678def
cherry-pick 이 성공하면 다음과 유사한 출력을 볼 수 있습니다.
[main 98765ab] Add new feature function
1 file changed, 1 insertion(+)
create mode 100644 feature.js
cherry-pick 이 예상대로 작동했는지 확인해 보겠습니다.
git log --oneline
이제 메인 브랜치의 기록에서 cherry-picked 커밋을 볼 수 있습니다.
98765ab (HEAD -> main) Add new feature function
abcd123 Add main application file
efgh456 Initial commit with README
파일이 존재하는지 확인할 수도 있습니다.
ls -la
출력에 feature.js가 나열되어 있는지 확인해야 합니다.
total 16
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 .
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 ..
drwxr-xr-x 8 labex labex 4096 Jan 1 00:00 .git
-rw-r--r-- 1 labex labex 29 Jan 1 00:00 app.js
-rw-r--r-- 1 labex labex 42 Jan 1 00:00 feature.js
-rw-r--r-- 1 labex labex 16 Jan 1 00:00 README.md
cherry-pick 작업은 기능 브랜치의 커밋을 메인 브랜치에 성공적으로 적용했습니다. 다음 단계에서는 필요한 경우 이 cherry-pick 을 취소하는 방법을 배웁니다.
이제 커밋을 성공적으로 cherry-pick 했으므로 이 작업을 취소하는 방법을 배우겠습니다. 이 단계에서는 최근 cherry-pick 을 취소하는 가장 간단한 방법인 git reset 명령을 사용합니다.
git reset 명령은 현재 브랜치 포인터를 지정된 커밋으로 이동하여 해당 지점 이후에 발생한 모든 커밋을 효과적으로 "취소"합니다. git reset 에는 세 가지 주요 모드가 있습니다.
--soft: 브랜치 포인터를 이동하지만 변경 사항을 스테이징된 상태로 유지합니다.--mixed (기본값): 브랜치 포인터를 이동하고 변경 사항을 스테이징 해제합니다.--hard: 브랜치 포인터를 이동하고 모든 변경 사항을 삭제합니다.cherry-pick 을 취소하기 위해 --hard 옵션을 사용하여 cherry-picked 커밋과 해당 변경 사항을 완전히 제거합니다.
먼저, cherry-picked 커밋이 있는 메인 브랜치에 있는지 확인하기 위해 현재 상태를 확인해 보겠습니다.
git log --oneline -n 3
다음과 유사한 출력을 볼 수 있습니다.
98765ab (HEAD -> main) Add new feature function
abcd123 Add main application file
efgh456 Initial commit with README
cherry-pick 작업을 취소하려면 --hard 옵션과 함께 git reset 을 사용하여 브랜치 포인터를 한 커밋 뒤로 이동합니다.
git reset --hard HEAD~1
이 명령은 Git 에 브랜치를 현재 HEAD ( ~1 부분은 "하나의 커밋 전"을 의미) 이전의 커밋으로 재설정하도록 지시합니다.
다음과 유사한 출력을 볼 수 있습니다.
HEAD is now at abcd123 Add main application file
cherry-pick 이 취소되었는지 확인해 보겠습니다.
git log --oneline
cherry-picked 커밋이 더 이상 기록에 없는 것을 볼 수 있습니다.
abcd123 (HEAD -> main) Add main application file
efgh456 Initial commit with README
feature.js 파일이 제거되었는지도 확인해 보겠습니다.
ls -la
출력에 feature.js가 포함되지 않아야 합니다.
total 12
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 .
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 ..
drwxr-xr-x 8 labex labex 4096 Jan 1 00:00 .git
-rw-r--r-- 1 labex labex 29 Jan 1 00:00 app.js
-rw-r--r-- 1 labex labex 16 Jan 1 00:00 README.md
축하합니다! git reset 을 사용하여 cherry-pick 작업을 성공적으로 취소했습니다. 이 방법은 깔끔하고 간단하지만 기록을 다시 작성하므로 공유 레포지토리에 푸시되지 않은 로컬 변경 사항에만 사용해야 합니다.
이전 단계에서는 git reset을 사용하여 cherry-pick 을 취소했습니다. 그러나 git reset은 기록을 다시 작성하므로 변경 사항을 이미 공유 레포지토리에 푸시한 경우 문제가 될 수 있습니다. 이 단계에서는 기록을 다시 작성하지 않고 git revert를 사용하여 cherry-pick 을 안전하게 취소하는 방법을 배웁니다.
git revert 명령은 이전 커밋에서 도입된 변경 사항을 실행 취소하는 새 커밋을 생성합니다. 기록에서 커밋을 제거하는 git reset과 달리, git revert는 변경 사항을 상쇄하는 새 커밋을 추가하여 커밋 기록을 보존합니다.
먼저, 되돌릴 내용이 있도록 커밋을 다시 cherry-pick 해보겠습니다.
## Get the commit hash from the feature branch
FEATURE_HASH=$(git log feature-branch --oneline | grep "new feature" | cut -d ' ' -f 1)
## Cherry-pick the commit
git cherry-pick $FEATURE_HASH
다음과 유사한 출력을 볼 수 있습니다.
[main 98765ab] Add new feature function
1 file changed, 1 insertion(+)
create mode 100644 feature.js
cherry-pick 이 성공했는지 확인해 보겠습니다.
git log --oneline -n 3
ls -la
기록에서 cherry-picked 커밋과 디렉토리 목록에서 feature.js 파일을 볼 수 있습니다.
이제 git revert를 사용하여 기록을 보존하면서 cherry-pick 을 취소해 보겠습니다.
git revert HEAD --no-edit
--no-edit 플래그는 Git 에 편집기를 열지 않고 기본 커밋 메시지를 사용하도록 지시합니다.
다음과 유사한 출력을 볼 수 있습니다.
[main abc9876] Revert "Add new feature function"
1 file changed, 1 deletion(-)
delete mode 100644 feature.js
커밋 기록을 확인해 보겠습니다.
git log --oneline -n 4
cherry-picked 커밋과 revert 커밋을 모두 볼 수 있습니다.
abc9876 (HEAD -> main) Revert "Add new feature function"
98765ab Add new feature function
abcd123 Add main application file
efgh456 Initial commit with README
이제 feature.js 파일이 제거되었는지 확인해 보겠습니다.
ls -la
출력에 feature.js가 포함되지 않아야 합니다.
total 12
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 .
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 ..
drwxr-xr-x 8 labex labex 4096 Jan 1 00:00 .git
-rw-r--r-- 1 labex labex 29 Jan 1 00:00 app.js
-rw-r--r-- 1 labex labex 16 Jan 1 00:00 README.md
git reset과 git revert는 모두 동일한 최종 결과 (cherry-pick 으로 도입된 변경 사항 제거) 를 달성하지만 다른 방식으로 수행합니다.
git reset은 기록에서 커밋을 제거하며, 이는 커밋이 다른 사람과 공유된 경우 문제를 일으킬 수 있습니다.git revert는 변경 사항을 실행 취소하는 새 커밋을 추가하여 커밋 기록을 보존하므로 공유 레포지토리에서 더 안전합니다.이러한 방법 중에서 선택하는 것은 특정 상황에 따라 다릅니다.
git reset을 사용합니다.git revert를 사용합니다.커밋을 cherry-pick 할 때, 커밋의 변경 사항이 현재 브랜치의 변경 사항과 충돌하는 경우 Git 에서 충돌이 발생할 수 있습니다. 이 단계에서는 cherry-pick 충돌을 처리하는 방법과 cherry-pick 작업을 중단하는 방법을 배웁니다.
먼저, cherry-pick 충돌이 발생할 시나리오를 만들어 보겠습니다.
## Switch to main branch and modify README.md
git checkout main
echo -e "## Cherry Pick Lab\n\nThis is the main branch README." > README.md
git commit -am "Update README in main branch"
## Switch to feature branch and make a conflicting change to README.md
git checkout feature-branch
echo -e "## Cherry Pick Lab\n\nThis README has been updated in the feature branch." > README.md
git commit -am "Update README in feature branch"
이제 메인 브랜치로 다시 전환하여 기능 브랜치의 커밋을 cherry-pick 해보겠습니다.
git checkout main
CONFLICT_HASH=$(git log feature-branch --oneline | grep "Update README in feature" | cut -d ' ' -f 1)
git cherry-pick $CONFLICT_HASH
두 브랜치 모두 README.md 에서 동일한 줄을 수정했으므로 충돌이 표시됩니다.
error: could not apply a1b2c3d... Update README in feature branch
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
충돌을 살펴보겠습니다.
git status
README.md 에서 충돌이 있음을 나타내는 출력을 볼 수 있습니다.
On branch main
You are currently cherry-picking commit a1b2c3d.
(fix conflicts and run "git cherry-pick --continue")
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
충돌된 파일의 내용을 살펴보겠습니다.
cat README.md
다음과 유사한 내용을 볼 수 있습니다.
## Cherry Pick Lab
<<<<<<< HEAD
This is the main branch README.
=======
This README has been updated in the feature branch.
>>>>>>> a1b2c3d... Update README in feature branch
충돌을 해결하려면 파일을 편집하고 유지할 변경 사항을 결정해야 합니다. README.md 를 수정하여 두 변경 사항을 모두 포함해 보겠습니다.
echo -e "## Cherry Pick Lab\n\nThis is the main branch README.\n\nThis README has also been updated with content from the feature branch." > README.md
이제 충돌을 해결된 것으로 표시하고 cherry-pick 을 계속 진행해 보겠습니다.
git add README.md
git cherry-pick --continue
Git 은 기본 커밋 메시지로 편집기를 엽니다. 편집기를 저장하고 닫아 cherry-pick 을 완료합니다.
경우에 따라 충돌을 해결하고 싶지 않고 cherry-pick 작업을 취소하는 것이 더 나을 수 있습니다. 다른 충돌을 만들고 cherry-pick 을 중단해 보겠습니다.
## Create another conflicting commit in feature branch
git checkout feature-branch
echo "// This will conflict with app.js in main" > app.js
git commit -am "Modify app.js in feature branch"
## Try to cherry-pick this commit to main
git checkout main
ANOTHER_CONFLICT=$(git log feature-branch --oneline | grep "Modify app.js" | cut -d ' ' -f 1)
git cherry-pick $ANOTHER_CONFLICT
다른 충돌이 표시됩니다. 이번에는 cherry-pick 을 중단해 보겠습니다.
git cherry-pick --abort
cherry-pick 작업이 취소되었고 작업 디렉토리가 이전 상태로 복원된 것을 볼 수 있습니다.
git status
출력:
On branch main
nothing to commit, working tree clean
cherry-pick 작업 중 충돌을 처리하는 것은 Git 사용자를 위한 필수 기술입니다. 충돌이 발생하면 세 가지 옵션이 있습니다.
git add 및 git cherry-pick --continue를 사용합니다.git cherry-pick --skip을 사용하여 충돌하는 커밋을 건너뜁니다.git cherry-pick --abort를 사용하여 전체 cherry-pick 작업을 중단합니다.가장 좋은 방법은 특정 상황과 프로젝트 요구 사항에 따라 다릅니다.
이 Lab 에서 Git 의 cherry-pick 기능에 대한 실질적인 경험을 얻었으며 cherry-pick 작업을 실행 취소하는 여러 가지 방법을 배웠습니다.
git reset을 사용하여 cherry-pick 을 실행 취소하는 방법을 배웠습니다.git revert를 사용하여 cherry-pick 을 안전하게 실행 취소하는 방법을 탐구했습니다.이러한 기술은 실제 프로젝트에서 Git 을 사용할 때 매우 중요합니다. Cherry-picking 을 사용하면 브랜치 간에 변경 사항을 선택적으로 적용할 수 있으며, cherry-pick 을 실행 취소하는 방법을 알면 실수로부터 복구하고 깨끗한 Git 기록을 유지하는 데 도움이 됩니다.
다양한 실행 취소 방법은 서로 다른 목적을 제공한다는 점을 기억하십시오.
git reset을 사용합니다.git revert를 사용합니다.git cherry-pick --abort를 사용합니다.이러한 옵션을 이해하면 특정 상황에 가장 적합한 방법을 선택할 수 있습니다.