git에 병합 한 후 git-svn dcommit은 위험합니까?
git-svn을 시험해보기위한 나의 동기는 쉬운 병합 및 분기입니다. 그런 다음 남자 git-svn (1)이 말합니다.
커밋하려는 분기에서는 git-merge 또는 git-pull을 실행하지 않는 것이 좋습니다. Subversion은 합리적이거나 유용한 방식으로 병합을 나타내지 않습니다. Subversion을 사용하는 사용자는 병합 한 내용을 볼 수 없습니다. 또한 SVN 분기의 미러 인 자식 분기를 병합하거나 가져 오면 dcommit이 잘못된 분기를 커밋 할 수 있습니다.
이것은 svn / trunk (또는 브랜치)에서 로컬 브랜치를 생성하고 해킹하고 svn / trunk로 다시 병합 한 다음 dcommit 할 수 없다는 것을 의미합니까? svn 사용자는 svn pre 1.5.x에서 병합 된 것과 같은 엉망이 항상 있었음을 알지만 다른 단점이 있습니까? 그 마지막 문장도 저를 걱정합니다. 사람들은 일상적으로 이런 종류의 일을합니까?
사실, --no-ff
git merge 옵션으로 더 나은 방법을 찾았습니다 . 이전에 사용한이 스쿼시 기술은 더 이상 필요하지 않습니다.
나의 새로운 워크 플로우는 다음과 같습니다 :
나는에서 dcommit있는 유일한 지점 및 그 클론 SVN 저장소 인 "마스터"지점을 가지고 (
-s
당신이 저장소의 표준 SVN 레이아웃을 가지고 가정trunk/
,branches/
그리고tags/
) :git svn clone [-s] <svn-url>
로컬 지점 "작업"에서 작업합니다 (
-b
"작업"분기 작성).git checkout -b work
"작업"분기에 로컬로 커밋합니다 (
-s
커밋 메시지를 사인 오프합니다). 속편에서는 3 번의 로컬 커밋을했다고 가정합니다.... (work)$> git commit -s -m "msg 1" ... (work)$> git commit -s -m "msg 2" ... (work)$> git commit -s -m "msg 3"
이제 SVN 서버에 커밋하려고합니다.
[결국] SVN 서버에서 커밋하고 싶지 않은 수정 사항을 숨기십시오 (주로 컴파일을 가속화하고 주어진 기능에 집중하기 위해 메인 파일에서 일부 코드에 주석을 달았습니다)
(work)$> git stash
SVN 저장소로 마스터 브랜치 리베이스 (SVN 서버에서 업데이트)
(work)$> git checkout master (master)$> git svn rebase
작업 지점으로 돌아가서 마스터와 리베이스
(master)$> git checkout work (work)$> git rebase master
예를 들어 다음을 사용하여 모든 것이 올바르게 작동하는지 확인하십시오.
(work)$> git log --graph --oneline --decorate
이제이 훌륭한
--no-ff
옵션을 사용하여 "작업"브랜치에서 "마스터"로 세 커밋을 모두 병합해야합니다.(work)$> git checkout master (master)$> git merge --no-ff work
로그 상태를 확인할 수 있습니다.
(master)$> git log --graph --oneline --decorate * 56a779b (work, master) Merge branch 'work' |\ | * af6f7ae msg 3 | * 8750643 msg 2 | * 08464ae msg 1 |/ * 21e20fa (git-svn) last svn commit
이제
amend
SVN 친구들의 마지막 커밋 을 편집 ( )하고 싶을 수도 있습니다 (그렇지 않으면 "Merge branch 'work'"메시지와 함께 단일 커밋 만 표시됩니다)(master)$> git commit --amend
마지막으로 SVN 서버에서 커밋
(master)$> git svn dcommit
작업으로 돌아가서 숨김 파일을 복구하십시오.
(master)$> git checkout work (work)$> git stash pop
git-svn으로 로컬 브랜치를 만들 수 있습니다. 로컬 브랜치를 사용하고 업스트림 svn 브랜치를 병합하기 위해 git을 사용하지 않는 한 괜찮습니다.
svn 서버를 추적하는 데 사용하는 "마스터"분기가 있습니다. 이것은 내가 위임 한 유일한 지점입니다. 내가 일을하고 있다면, 토픽 브랜치를 만들고 해결합니다. 커밋하고 싶을 때 다음을 수행합니다.
- 주제 지점에 모든 것을 커밋
- git svn rebase (resolve any conflicts between your work and svn)
- git checkout master
- git svn rebase (this makes the next step a fast-forward merge, see Aaron's comments below)
- git merge topic_branch
- resolve any merge conflicts (there shouldn't be any at this point)
- git svn dcommit
I also have another situation where I need to maintain some local changes (for debugging) that should never be pushed up to svn. For that, I have the above master branch but also a branch called "work" where I normally do work. Topic branches are branched off work. When I want to commit work there, I checkout master and use cherry-pick to pick the commits from the work branch that I want to commit to svn. This is because I want to avoid committing the three local change commits. Then, I dcommit from the master branch and rebase everything.
It is worthwhile running git svn dcommit -n
first to make sure that you are about to commit exactly what you intend to commit. Unlike git, rewriting history in svn is hard!
I feel that there must be a better way to merge the change on a topic branch while skipping those local change commits than using cherry-pick, so if anybody has any ideas they would be welcome.
Simple solution: Remove 'work' branch after merging
Short answer: You can use git however you like (see below for a simple workflow), including merge. Just make sure follow each 'git merge work' with 'git branch -d work' to delete the temporary work branch.
Background explanation: The merge/dcommit problem is that whenever you 'git svn dcommit' a branch, the merge history of that branch is 'flattened': git forgets about all merge operations that went into this branch: Just the file contents is preserved, but the fact that this content (partially) came from a specific other branch is lost. See: Why does git svn dcommit lose the history of merge commits for local branches?
(Note: There is not much that git-svn could do about it: svn simply doesn't understand the much more powerful git merges. So, inside the svn repository this merge information cannot be represented in any way.)
But this is the whole problem. If you delete the 'work' branch after it has been merged into the 'master branch' then your git repository is 100% clean and looks exactly like your svn repository.
My workflow: Of course, I first cloned the remote svn repository into a local git repository (this may take some time):
$> git svn clone <svn-repository-url> <local-directory>
All work then happens inside the "local-directory". Whenever I need to get updates from the server (like 'svn update'), I do:
$> git checkout master
$> git svn rebase
I do all my development work in a separate branch 'work' that is created like this:
$> git checkout -b work
Of course, you can create as many branches for your work as you like and merge and rebase between them as you like (just delete them when you are done with them --- as discussed below). In my normal work, I commit very frequently:
$> git commit -am '-- finished a little piece of work'
The next step (git rebase -i) is optional --- it's just cleaning up the history before archiving it on svn: Once I reached a stable mile stone that I want to share with others, I rewrite the history of this 'work' branch and clean up the commit messages (other developers don't need to see all the little steps and mistakes that I made on the way --- just the result). For this, I do
$> git log
and copy the sha-1 hash of the last commit that is live in the svn repository (as indicated by a git-svn-id). Then I call
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
Just paste sha-1 hash of our last svn commit instead of mine. You may want to read the documentation with 'git help rebase' for the details. In short: this command first opens an editor presenting your commits ---- just change 'pick' to 'squash' for all those commits that you want to squash with previous commits. Of course, the first line should stay as a 'pick'. In this way, you can condense your many little commits into one or more meaningful units. Save and exit the editor. You will get another editor asking you to rewrite the commit log messages.
In short: After I finish 'code hacking', I massage my 'work' branch until it looks how I want to present it to the other programmers (or how I want to see the work in a few weeks time when I browse history).
In order to push the changes to the svn repository, I do:
$> git checkout master
$> git svn rebase
Now we are back at the old 'master' branch updated with all changes that happened in the mean time in the svn repository (your new changes are hidden in the 'work' branch).
If there are changes that may clash with your new 'work' changes, you have to resolve them locally before you may push your new work (see details further below). Then, we can push our changes to svn:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
Note 1: The command 'git branch -d work' is quite safe: It only allows you to delete branches that you don't need anymore (because they are already merged into your current branch). If you execute this command by mistake before merging your work with the 'master' branch, you get an error message.
Note 2: Make sure to delete your branch with 'git branch -d work' between merging and dcommit: If you try to delete the branch after dcommit, you get an error message: When you do 'git svn dcommit', git forgets that your branch has been merged with 'master'. You have to remove it with 'git branch -D work' which doesn't do the safety check.
Now, I immediately create a new 'work' branch to avoid accidentally hacking on the 'master' branch:
$> git checkout -b work
$> git branch # show my branches:
master
* work
Integrating your 'work' with changes on svn: Here is what I do when 'git svn rebase' reveals that others changed the svn repository while I was working on my 'work' branch:
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
More powerful solutions exist: The presented workflow is simplistic: It uses the powers of git only within each round of 'update/hack/dcommit' --- but leaves the long-term project history just as linear as the svn repository. This is ok if you just want to start using git merges in small first steps in a legacy svn project.
When you become more familiar with git merging, feel free to explore other workflows: If you know what you are doing, you can mix git merges with svn merges (Using git-svn (or similar) just to help out with svn merge?)
Greg Hewgill answer on top is not safe! If any new commits appeared on trunk between the two "git svn rebase", the merge will not be fast forward.
It can be ensured by using "--ff-only" flag to the git-merge, but I usually do not run "git svn rebase" in the branch, only "git rebase master" on it (assuming it is only a local branch). Then afterwards a "git merge thebranch" is guaranteed to be fast forward.
A safe way to merge svn branches in git is to use git merge --squash. This will create a single commit and stop for you to add a message.
Let's say you have a topic svn branch, called svn-branch.
git svn fetch
git checkout remotes/trunk -b big-merge
git merge --squash svn-branch
at this point you have all the changes from the svn-branch squashed into one commit waiting in the index
git commit
Rebase the local git branch onto the master git branch then dcommit and that way it looks like you did all those commits in sequence so svn people can see it linearly as they are accustomed to. So assuming you have a local branch called topic you could do
git rebase master topic
which will then play your commits over the master branch ready for you to dcommit
참고URL : https://stackoverflow.com/questions/190431/is-git-svn-dcommit-after-merging-in-git-dangerous
'Programming' 카테고리의 다른 글
데이터 프레임에서 그룹 내 행 번호 매기기 (0) | 2020.06.27 |
---|---|
파일의 각 줄에 대해 명령을 어떻게 실행합니까? (0) | 2020.06.27 |
목록은 스레드로부터 안전합니까? (0) | 2020.06.27 |
파워 미터에 빨간색과 초록색 사이의 색상을 생성 하시겠습니까? (0) | 2020.06.27 |
파이썬에서 목록 항목 세트를 구성하는 방법은 무엇입니까? (0) | 2020.06.27 |