Git 공식 홈페이지에서 이 소개를 읽고 더욱 혼란스러웠습니다
Git를 사용하면 비행기나 기차를 타고 있더라도 업데이트를 자주 제출하고 네트워크가 있을 때 원격 창고에 업로드할 수 있습니다. 마찬가지로 VPN에 연결하지 않고도 집에 가는 길에도 계속 작업할 수 있습니다. 다른 버전 제어 시스템에서는 이것이 거의 불가능하거나 매우 번거롭습니다.
링크주소》》》
팀에 프로그래머 A, B, C 3명이서 버전 관리를 위해 git을 사용하는 쇼핑몰 프로젝트가 시작되었습니다. 총 개발일수는 10일이며, 1일차부터 5일차까지 A, B, C가 모두 함께 개발되어 하나의 버전으로 제출됩니다. 하지만 C씨는 6일째부터 리모콘에 복종하지 않고 늘 직접 수정하고 만들어 나갔습니다. 전체 프로젝트에는 많은 파일이 있습니다. C는 프로젝트의 GlobalFunction.php 파일을 여러 번 변경하고 많은 기능을 수정하며 자체 기능도 많이 추가합니다. 개발이 계속됨에 따라 C는 GlobalFunction.php 파일을 계속 수정하게 됩니다. 항상 원격에 제출되었던 A와 B도 GlobalFunction.php 파일을 자주 수정해야 하지만 A와 B는 Git 원격에 동기화된 상태를 유지합니다.
지난 10일 동안 C는 인터넷에 접속할 수 있었고 이후 C는 리모트에 제출됐다. 하지만 C 컴퓨터의 GlobalFunction.php는 Git 원격의 GlobalFunction.php와 완전히 다르며 원격 파일은 20개 이상의 버전을 거쳤습니다. 그리고 C 자신의 컴퓨터도 수십 가지의 다양한 버전을 경험했습니다.
git 소개의 설명에 따르면 이 경우 Git이 자동으로 merge를 할 수 있나요? 자동으로 병합하는 방법은 무엇입니까?
C는 GlobalFunction.php에 많은 기능을 추가했으며 이 기간 동안 많은 버전을 거쳤습니다.
Git을 소개하는 많은 글들이 원격지로 푸시하지 않고 인터넷에 연결하지 않고도 사용할 수 있다는 점에 초점을 맞추고 있는 것을 보니 정말 이해하기 어렵습니다. SF에서 물었을 때 많은 사람들이 /q/1010000000605934#c-1020000000606050-1050000000609657을 푸시할 필요가 없다고 말했는데, 이는 더욱 혼란스럽습니다. 푸시할 필요가 없습니다. 1년 또는 10년 안에 푸시하지 않아도 여전히 공동 작업이 가능합니다. 10년 후에도 인터넷에 연결하여 푸시할 수 있습니다. 자동으로 병합할 수 있습니다
시나리오를 극단적으로 밀어붙이는 것은 나쁜 논쟁 방법입니다.
우선 제출의 목적이 무엇입니까? 단순히 코드를 다른 사람과 동기화하는 것이라면 git에는 실제로 하이라이트가 없습니다. 오프라인 제출도 오해를 받을 수 있다는 점입니다.
개인적으로 제출의 목적은 코드를 임시로 저장하는 것(Shenma의 후속 롤백을 용이하게 하기 위한 버전 관리)이라고 생각하고, 두 번째는 코드의 단계 노드 역할을 하는 것(이 기능이 완료되면 제출), 세 번째는 이를 서버 동기화에 제출하고 다른 사람들과 공유하는 것입니다.
Git의 오프라인 제출은 위의 목적 중 한두 가지를 매우 효과적으로 달성할 수 있습니다. 그리고 오프라인으로 제출하기 때문에 서버와 동기화하기 전에 제출 기록을 쉽게 수정할 수 있습니다. 예를 들어 메소드를 작성했는데 작동하는데 리팩토링을 하고 싶은데 리팩토링 후에 제대로 작동할지 확신이 없어서 리팩토링이 깨지면 롤백할 수 있도록 먼저 버전을 제출합니다. 리팩토링 완료 후 다시 제출하겠습니다. 이 시점에서 동일한 기능에 대한 두 개의 제출이 있으며 다른 사람에게 "XX 기능 완료"라는 제출 하나만 표시되도록 하여 두 제출을 쉽게 병합할 수 있습니다. 최종 병합 후 코드 저장소는 매우 깨끗합니다. 제출해야 하는 모든 제출 기록이 "Test XXX" 또는 "Try XXX"와 같은 제출 없이 릴리스 노트에 직접 작성될 수 있습니다. 동일한 결과를 바탕으로 한 번 작성한 코드를 여러 번 제출할 수도 있습니다. 예를 들어 함수를 세 개 작성하면 세 번 제출하고 최종적으로 서버에 동기화할 수 있습니다. 네트워크 없음 코드)는 한 번만 제출할 수 있으며 "A, B, C 세 가지 기능 완료"라고 작성하면 다른 사람이 코드를 보는 것이 편리하지 않으며 A, B, 롤백하는 데 도움이 되지 않습니다. 그리고 C.
그래서 Git의 오프라인 제출은 유연성을 제공합니다. 오프라인 제출 시 서버가 필요하지 않으며 Air가 자동으로 공동 작업을 완료한다는 의미는 아닙니다. 제가 처음에 "장면을 극단적으로 밀어붙이는 것은 나쁜 논쟁 방법이다"라고 말한 것이 바로 이것이다. svn에 비해 git은 더 많은 협업 방법을 갖고 있고 더 유연하지만 여전히 협업하고 코드를 병합해야 하는 문제를 피할 수는 없습니다.
코드를 병합하는 과정에서 SVN과 마찬가지로 충돌도 발생하므로 조건이 허락한다면 적시에 코드를 서버와 동기화하는 것이 좋습니다. 그러나 git은 콘텐츠 기반 추적 버전이고 svn은 기본 파일 추적 버전이므로 git merge는 svn보다 훨씬 안정적입니다. 즉, 동일한 상황에서 git은 svn보다 충돌이 발생할 가능성이 훨씬 적습니다.
마지막으로 git의 오프라인 제출 기능과 git 브랜치가 특히 사용하기 쉽다는 사실로 인해 로컬 다중 브랜치 관리 기능을 구현할 수도 있습니다. 로컬에서 분기를 열고 로컬로 제출한 다음 병합하여 서버에 푸시합니다. 다른 사용자에게는 이 분기가 존재하지 않지만 언제든지 작업 상태를 전환할 수 있습니다(새 기능을 작성하거나 다시 전환). 버그를 수정하기 위해). SVN은 분기를 잘라낼 수도 있지만 분기가 로컬에만 존재할 수는 없습니다. 분기 협업을 채택하면 다른 분기가 신경 쓸 필요가 없는 분기가 많아지게 됩니다. 더 문제가 되는 점은 새로운 기능을 절반쯤 작성했는데 돌아가서 버그를 수정해야 하는 경우 미완성 코드만 svn 서버에 제출하면 된다는 점입니다. 제 개인적인 의견으로는 (미완성 코드를 리포지토리 서버에 제출) 이것은 매우 나쁜 동작이지만 git에서는 브랜치가 오프라인이기 때문에 제출한 후 버그를 수정하기 위해 다시 전환하고 다시 전환한 다음 기능이 완료된 후 제출 레코드를 병합하면 모든 것이 완벽합니다. .
양 당사자가 서로 다른 파일을 변경하거나 동일한 파일의 다른 부분을 변경하는 경우 git이 자동으로 이를 병합할 수 있습니다.
동일한 파일의 동일한 부분이 수정되면 git은 자동으로 병합할 수 없습니다. 이 상황을 "충돌"이라고 합니다. Git은 두 당사자의 최신 버전을 나열한 다음 병합을 수행한 사람을 나열합니다(예: 예 C), 수동으로 편집하세요.
실제 개발에서는 두 사람이 이 파일에 기능만 추가하면 자동으로 병합될 수 있는데, 주로 같은 줄을 수정할 때 충돌이 발생합니다.
보충 답변:
많은 소개에서 git이 오프라인으로 커밋될 수 있다는 점을 강조합니다. 이는 svn과 비교하기 위한 것입니다. svn에서는 서버에만 완전한 저장소가 있고 클라이언트의 코드 기록은 완전하지 않습니다. git의 각 클라이언트는 완전한 저장소이며 푸시 및 풀 작업은 실제로 여러 개의 완전한 저장소 간의 동기화입니다.
이것의 장점은 서버가 중단되거나 손실되는 것을 두려워하지 않는다는 것입니다. 모든 사람은 완전한 버전 라이브러리를 가지고 있습니다. 이는 Linux가 git을 개발하는 출발점이기도 합니다. 더 나쁜 것은 모든 사람이 코드(기록의 모든 수정 사항)가 실수로 유출될 수 있는 완전한 저장소를 가지고 있다는 것입니다.
드디어 제가 잘 대답할 수 있는 질문이 생겼습니다
먼저 질문의 가설에 대해 이야기해 보겠습니다.
C는 6일째부터 리모컨 조작을 중단하고 혼자 놀기 시작했습니다. 분산되지 않음은 네트워크가 사용 가능한 경우를 의미하며 며칠 후에 원격 장치와 동기화되지 않는다는 의미는 아닙니다.
파일 이름이이므로 이 파일은 거의 수정되지 않습니다(또는 동일한 줄이 거의 수정되지 않음). Python
에GlobalFunction.php
의 과 유사하며 때로는 새로운 파일일 수도 있습니다. 버전이 출시될 때만setup.py
변수를 수정하세요.version
GIT의 브랜치 개념에 대한 개인적 이해는 하나 이상의 브랜치를 기반으로 더 빠른 공동 개발이 가능하다는 것입니다. 예를 들어 창고라는 브랜치가 있으면 A, B, C가 됩니다. 때로는 이 공통 브랜치
foo
를 기반으로 로컬 브랜치가 만들어지기도 합니다. 예를 들어 A의 로컬 브랜치는master
, C의 로컬 브랜치는master
이라고 합니다. 그게 나오나요?a-dev
으아아아b-dev
c-dev
둘째, 질문에서 언급한 합병에 대해 이야기해보겠습니다.C가 을 기반으로 로컬 브랜치를
만들면 C는 로컬 브랜치에 영향을 주지 않고 항상 로컬 마스터 브랜치를 업데이트할 수 있습니다(이때 항상
에는 어떻게 반영되나요? 간단합니다. GIT가 이미 생각해 냈습니다.master
에 있을 수 있습니다. 지점):c-dev
으아아아c-dev
그럼 로컬c-dev
이 업데이트되면으아아아
일 수 있음), 로컬master
위 단계를 통과한 후 발생할 수 있는 상황은 두 가지뿐입니다. 1. 병합 충돌 발생,c-dev
실패 2. 충돌 없음(자동최신 상태가 다릅니다. 로컬
rebase
병합merge
master
1이 발생하는 경우 GIT는 충돌을 자동으로 해결하지 않지만 자동으로 병합을 시도할 수 있습니다(c-dev
). 실패할 경우 일반적으로 동일한 내용을 수정하는 다른 제출물을 충돌이라고 합니다. 동일한 파일의 파일. 내용의 줄(여러 줄)은 개발자가 직접 충돌을 해결해야 합니다.merge
개인 요약Branch는 다른 중앙 집중식 버전 관리 시스템과 구별되는 GIT의 킬러 기능입니다(
).충돌이 발생하면 SVN은 한 줄씩 비교하고 Git은 줄 추가, 삭제, 줄 수정 등의 작업을 기록하므로 병합 작업이 더 쉽습니다
당신이 언급한 문제는 지점을 통해서만 해결될 수 있습니다
간단히 말하면 자동 병합이 가능할 수도 있고 불가능할 수도 있습니다.
Git의 각 커밋은 diff를 저장합니다. 커밋을 표시하고 살펴볼 수 있습니다. diff는 원래 수정된 줄 전후의 여러 줄을 일치시키려고 시도합니다. 일치할 수 있으면 diff가 자동으로 병합될 수 있습니다.
예를 들어 C의 패치가 다섯 번째 줄의 값을 수정하면 커밋되지 않습니다. A와 B는 GlobalFunction.php에 새로운 기능을 추가했습니다. 이 기능은 C가 병합될 때 Cherry-Pick을 통해 병합을 완료할 수 있습니다.
두 당사자 모두 동일한 장소를 수정한 경우 충돌을 수동으로 해결해야 합니다.