co working 을 하다보면 효율적인 code관리가 필요하고 그것을 위한 tool이 바로 git이다.

몇가지 시나리오를 통해 깃을 배워보자.

stash와 reset에 대한 개념이 없으면 이 글을 이해하기 힘들다.

우선 아래 링크에서 이 개념을 익히고 이글을 보는 것을 추천한다.


Problem 1. local branch switching (stash, commit, reset, etc…)by Daejin

  • create and switch to a new branch: git checkout -b new_branch
  • make some changes and add/commit them.
  • make another change but don’t commit.
  • try to switch back the original branch: git checkout master
  • check if the following error occurs
  • error: Your local changes to the following files would be overwritten by checkout: changed files. Please, commit your changes or stash them before you can switch branches.Aborting
    • Q1) There are the following ways to switch branch in this case. Try 1~3 and write the differences:
      1. commit the change
      2. stash the change
      3. hard reset

풀이

  • Q1
  1. 변경한 파일을 add, commit 후 branch를 이동한다.
    $ git add
    $ git commit -m “${message}”
    $ git checkout ${master}

commit 결과 commit결과

  1. 변경 내역을 stash를 사용하여 stack 영역에 올린후 branch를 이동
    $ git stash
    $ git checkout ${master}
    stack 저장된 내용을 복원하려면
    $ git stash apply
    혹은
    $ git stash pop
    pop을 해줘야 stack 영역에 있던 내용이 지워진다.

stash 결과 stash결과

  1. reset –hard 를 사용하여 index 와 worktree를 비우고 branch를 이동한다.
    문제점은 작업하고 있던 파일의 내용이 사라진다는 것이다.

reset –hard 결과 reset --hard 결과


이어서 branch들을 병합할때 사용하는 rebase와 cherry-pick 을 문제를 통해서 알아보자.

Problem 2. dependencies (local/remote rebase) and cherry-pickby Daejin

  • create two branches ‘a’ and ‘b’
  • switch to branch ‘b’ and create a file b.txt and add any text in it. git add and commit it.
  • switch back to branch ‘a’ and create a file a.txt.
    • Q1) There are two ways (except git merge) to apply changes in branch ‘b’ to branch ‘a’. Try those two ways. What is the difference and when to apply each?
      1. cherry-pick
      2. rebase
    • Q2) If branch ‘b’ is removed after all commits in branch ‘b’ are pushed but not merged in remote branch, how to apply changes in branch ‘b’ to branch ‘a’?
    • Q3) update the local master branch to the latest
    • Q4) what is push command if you want to upload some changes in local branch to remote branch named ‘a’ if such a branch exists?

풀이

Question을풀기전 초기상태 !Question을 풀기전 초기상태

  • Q1

    1. cherry-pick
      $ git cherry-pick b
      를 하면 아래와 같은 error가 발생한다.

다른 branch를 merge하기 위해서는 work tree에 있는 것들을 staged상태로 올려 주어야 한다. 다른 branch를 merge하기 위해서는 work tree에 있는 것들을 staged상태로 올려 주어야 한다.

1
    주의해야할 것은 commit 명령이 아닌 add와 cherry-pick --continue 명령으로 work tree에 있는 파일을 staged 상태로 만들어 준다.

cherry-pick 결과 cherry-pick 결과

1
2
3
4
5
6
7
8
9
2.  rebase
    
    rebase도 마찬가지로  
    $ git rebase b  
    를 하면 error가 발생한다.  
    그래서  
    $ git add ${file}  
    $ git rebase --continue  
    를 하면 아래와 같은 결과가 나온다.

rebase 결과 rebase 결과

1
2
    b branch에 있던 b.text file이 a branch에도 나타나는 것을 확인할 수 있다.  
    하지만 cherry-pick 과 rebase의 차이는 이력 결과 graph를 보면 알 수 있다.

merge 이 후 directory merge 이후 directory

  • Q2

    b branch내의 b.text파일을 수정하고 branch가 지워졌을 때 이것을 어떻게 a branch에 적용할 수 있는지 설명하겠다.

q2를 위한 상태 설정 q2를 위한 상태설정

b 에서bbb를 추가 b에서 bbb를 추가

b branch를 제거 b branch를 제거

a branch 내의 b 파일: bbb가 반영되지 않음 a branch 내의 b 파일: bbb가 반영되지 않음

사라진 branch의 스냅샷 를 기억하는 id를 통해 수정내용을 불러옴 사라진 branch의 스냅샷 를 기억하는 id를 통해 수정내용을 불러옴

1
2
3
최종적으로 b.text파일에  
b bbb  
가 씌여있는 것 을 확인할 수 있다.
  • Q3
    branch들을 cherry-pick과 rebase를 사용해서 병합하고 나면 master branch가 이력상으로 뒤쪽에 위치하는 것을 graph를 통해 확인 할 수 있다. master branch에서 병합된 branch를 merge 하면 최신상태를 반영할 수 있다.
    $ git checkout master
    $ git merge ${branch_name}

  • Q4
    아래의 명령을 통해 remote repository 상의 master branch가 아닌 다른 branch에 push 할 수 있다.
    $ git push origin ${local_branch}:${remote_branch}
    master branch가 아닌 다른 branch를 pull하고 싶다면
    $ git pull origin ${remote_branch}:${local_branch}
    좀더 알고 싶다면 아래의 링크를 보자
    remote branch의 모든것


Problem 3. Merge conflictby

Daejin

  • switch to master branch and create a file c.txt

  • fill any content in c.txt and commit.

  • create two new branches ‘c’ and ‘d’

  • switch to branch ‘c’ and modify content in c.txt. Also commit it.

  • switch to branch ‘d’ and modify content in c.txt and commit it.

  • Try apply changes in branch ‘c’ to branch ‘d’ and check if the following error occurs

  • CONFLICT (content): Merge conflict in c.txterror: Failed to merge in the changes.
    or
    error: could not apply …… hint: after resolving the conflicts, mark the corrected paths

    • Q1) How to resolve this issue and what is the difference

      1. cherry-pick
      2. rebase

풀이

  • Q1 초기설정대로 진행을 하면 아래와 같은 상태가 된다.

problem3 초기상태 problem3 초기상태 1. cherry-pick
$ git cherry-pick ${branch}
명령을 하면 아래와 같은 오류가 발생한다.

충돌오류 충돌오류

1
    충돌파일을 찾아서 내용을 수정 해주고

충돌이 발생된 파일 충돌이 발생된 파일

1
    add 와 cherry-pick --continue 명령을 통해 수정해준 파일을 staged상태로 만든 후 branch를 merge 한다.

과정 과정

1
2
    주의사항은 commit 명령을 안한다는 것이다.  
    최종적으로 merge된 log는 아래와 같다.

merge된 branch merge된 branch

1
    이후 mater branch 최신상태로 반영하려면 아래와 같다.

master를 최신상태로 master를 최신상태로 2. rebase

1
2
    $ git rebase ${branch}  
    명령을 하면 아래와 같은 오류가 발생한다

$git rebase ${branch} 이후 $git rebase ${branch} 이후

1
    충돌이 발생한 파일을 충돌이 발생하지 않도록 수정한다.

충돌발생한 파일 충돌발생한 파일

1
2
3
4
5
    이후  
    $ git add ${file}  
    $ git rebase --continue
    
    를 해주면 두 branch가 merge 된다.

rebase 결과 rebase 결과

1
    최신사항을 master branch에 반영한 결과 아래와 같다.

master에 최신사항 반영 master에 최신사항 반영

이어서 commit –amend 명령의 사용과 하나의 remote repository를 공유하면서 여러개의 local repository에서 작업을 할 때 발생할 수 있는 문제에 대해서 다루어 보겠다.
아래의 링크를 참고하면서 보자.

우선 reset 과 revert의 명확한 차이를 짚고 넘어가자.
짧게 말한다면 이전에 했던 rebase와 cherry-pick의 차이와 비슷하게
이력을 남기고 돌아가느냐 지우고 돌아가느냐 이다.

reset과 revert의 차이1
reset과 revert의 차이2
reset
revert


Problem 4. patch set (amend or paste change-id) my patchset and other patch set.by Daejin

  • switch back to master branch

  • made some changes and commit it.

  • Push it to the remote repository

    • Q1) If you want to modify your last commit which you just pushed and upload it as a patch set in remote repository, how to do that?
    • Q2) Suppose another user uploaded a commit in remote repository and you want to modify and upload it as patch set before merged. How to do that?
    • Q3) Suppose another user uploaded a commit in remote repository and you don’t like it at all. You don’t want to use any of that changes but want to upload a completely new patch set in that commit. How to do that?

solution

  • Q1
    파일 수정을 한다.
    $ git add ${file name}
    $ git commit –amend
    $ git push origin +master

    ammend를 하면 커밋이력이 삭제되어서 remote 와 local repository간의 log 싱크가 맞지 않아서 push가 되지 않는다.
    +옵션을 주어 강제로 push 해주어야 한다.
    이것에 따라 발생할 수 있는 문제점은 ammend하기 이전의 log가 remote ropository에 없어지기 때문에 유의하자

amend 이후 log amend 이후 log

push를 했을 때 오류
push를 했을 때 오류

강제 push후
강제 push후

  • Q2
    두가지 선택사항이 있다.
    이력을 남기느냐 강제로 바꾸느냐 강제로한다면 위에 처럼 +옵션을 주면 되지만
    후자의 문제점은 다른 모든 user들의 remote 이력과 싱크에 차이가 생겨 충돌을 야기시키게 된다.
    그래서 안전한 방법은 전자의 reset과 revert를 잘 사용하여 remote의 log이력과 충돌이 발생하지 않게
    another user upload하기 전의 이력으로 reset을 사용해 돌아가서 pull을 한다.
    파일을 수정한 뒤 commit하고 다시 remote repository에 push한다.

    $ git branch -b ${new_branch}
    $ git checkout master
    $ git reset –hard ${another user의 upload 이전 시점}
    $ git pull
    $ git checkout ${new_branch}
    $ git merge ${mater}
    충돌부분 수정
    $ git checkout master
    $ git merge ${new_branch}
    $ git push origin master

  • Q3
    이것도 마찬가지로 두가지 선택사항이 있다.
    강제로 하는 것은 Q2와 같고
    이력을 남기는 방법을 설명하겠다.

    $ git branch -b ${new_branch}
    $ git checkout master
    $ git reset –hard ${another user의 upload 이전 시점}
    $ git pull
    $ git reset –hard ${another user의 upload 이전 시점}
    $ git merge ${new_branch}
    $ git push origin master

**Problem 5.** already merged commit in previous commit logby \[Daejin\](mailto:[daejin.hyeon@thordrive.ai](mailto:daejin.hyeon@thordrive.ai))

  • : Suppose you cherry-picked a commit ‘a’ from remote repository and create other commits ‘b’ and ‘c’ on top of it. If you try to push commits ‘b’ and ‘c’ to remote repository after commit ‘a’ is already merged, the following error might occur.

  • ! [remote rejected] HEAD -> refs/for/master (change ***closed)

    error: failed to push some refs to ‘https://***@***

    Q1) What should have done to prevent such errors?

  • solution

    • Q1
      문제 4와 5의 차이는 another user가 remote repository commit 한 것을 아직 merge하지 않았는지 이미 되었는지 이다.
      이미 merge가 되었다면 merge를 취소 해주면 된다.
      git reset의 경우 –merge 옵션으로 merge를 취소할 수 있고,
      git revert의 경우는 –mainline 숫자 ${취소할 병합 commit ID}

git log나 branch 등의 효과적으로 보기 위한 tool인 pretty git branch grpah 라는 것이 있다.

$ gedit ~/.gitconfig 로 들어가서

[alias] lg1 = log –graph –abbrev-commit –decorate –format=format:’%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)’ –all lg2 = log –graph –abbrev-commit –decorate –format=format:’%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n’’ %C(white)%s%C(reset) %C(dim white)- %an%C(reset)’ –all lg = !”git lg1”

의 내용을 복붙해주자. alias는 긴 명령어를 짧게 줄여주는 역활을 한다. $ git lg $ git lg1 $ git lg2 명령을 command 창에 써보자.

Tags:

Categories:

Updated:

Leave a comment