깃과 수은 - 비교 및 대조
한동안 저는 개인적인 프로젝트를 위해 전복을 사용해 왔습니다.
Git와 Mercurial, 그리고 DVCS에 대한 좋은 소식이 점점 더 많이 들려오고 있습니다.
저는 DVCS 전체를 시도해보고 싶지만, 두 옵션 모두 잘 모릅니다.
머큐리얼과 깃의 차이점은 무엇입니까?
참고: 저는 어떤 것이 "최고"인지 심지어 어떤 것부터 시작해야 하는지 알아내려는 것이 아닙니다.주로 비슷한 부분이 있고, 다른 부분이 있는 핵심 영역을 찾고 있는데, 그 이유는 실행과 철학 면에서 어떻게 다른지에 관심이 있기 때문입니다.
고지 사항: 나는 Git를 사용하고 Git 메일링 리스트에서 Git 개발을 팔로우하며 Git(주로 Gitweb)에 약간의 기여도 합니다.설명서와 FreeNode의 #revctrl IRC 채널에 대한 논의를 통해 Mercurial을 알고 있습니다.
이 글을 작성하기 위해 머큐리얼에 대한 도움을 제공해주신 #머큐리얼 IRC 채널의 모든 분들께 감사드립니다.
요약
여기서 PHP Markdown / Multi Markdown / Markdown의 마루쿠 확장과 같은 테이블에 대한 구문이 있으면 좋습니다.
- 리포지토리 구조:Mercurial은 두 개 이상의 부모와의 문어 병합을 허용하지 않으며 커밋되지 않은 개체에 태그를 지정할 수 없습니다.
- 태그: 머큐리얼은 버전을 사용합니다.
.hgtags
저장소별 태그에 대한 특수 규칙이 포함된 파일 및 로컬 태그 지원.hg/localtags
Git 태그는 참조 위치에 있습니다.refs/tags/
네임스페이스는 기본적으로 가져오기 시 자동으로 수행되며 명시적인 푸시가 필요합니다. - 분기:Mercurial의 기본 워크플로우는 익명의 헤드를 기반으로 합니다. Git는 가벼운 이름의 분기를 사용하며 원격 저장소의 분기를 따르는 특별한 종류의 분기(원격 추적 분기)를 가지고 있습니다.
- 개정 이름 및 범위:Mercurial은 리비전 번호, 저장소에 대한 로컬 및 기본 상대 리비전(팁에서 현재 분기까지 카운트) 및 이 로컬 번호에 대한 리비전 범위를 제공합니다. Git는 분기 팁에 대한 리비전을 참조하는 방법을 제공하며 리비전 범위는 위상적입니다(리비전 그래프 기반).
- Mercurial은 이름 변경 추적을 사용하는 반면 Git는 이름 변경 탐지를 사용하여 파일 이름을 처리합니다.
- 네트워크:Mercurial은 SSH 및 HTTP "스마트" 프로토콜과 정적 HTTP 프로토콜을 지원합니다. 현대의 Git는 SSH, HTTP 및 GIT "스마트" 프로토콜 및 HTTP(S) "덤" 프로토콜을 지원합니다.두 제품 모두 오프라인 전송을 위한 번들 파일을 지원합니다.
- Mercurial은 확장(플러그인) 및 API를 사용합니다. Git는 스크립트 기능과 설정된 형식을 가지고 있습니다.
머큐리얼과 깃이 다른 점이 몇 가지 있지만, 비슷한 점이 또 있습니다.두 프로젝트 모두 서로의 아이디어를 차용합니다.예를들면hg bisect
머큐리얼(이전의 이등분 확장)의 명령은 다음에서 영감을 받았습니다.git bisect
Git에서의 명령, 생각하는 동안.git bundle
에서 영감을 받았습니다.hg bundle
.
리포지토리 구조, 수정사항 저장
Git에서 객체 데이터베이스에는 네 가지 유형의 객체가 있습니다: 파일의 내용을 포함하는 Blob 객체, 파일 이름과 파일 권한의 관련 부분을 포함하는 디렉토리 구조를 저장하는 계층적 트리 객체, (파일에 대한 실행 가능한 권한, 심볼릭 링크) 작성자 정보를 포함하는 커밋 객체,(프로젝트의 최상위 디렉터리 트리 개체를 통해) 커밋으로 표시되는 리비전의 저장소 상태 스냅샷에 대한 포인터, 0개 이상의 상위 커밋에 대한 참조 및 다른 개체를 참조하고 PGP/GPG를 사용하여 서명할 수 있는 태그 개체.
Git는 객체를 저장하는 두 가지 방법을 사용합니다. 즉, 각 객체가 별도의 파일에 저장되는 느슨한 형식(해당 파일은 한 번 작성되고 수정되지 않음)과 많은 객체가 하나의 파일에 델타 압축되어 저장되는 패킹 형식입니다.연산의 원자성은 새 객체에 대한 참조가 객체를 작성한 후(원자적으로 create + rename trick을 사용하여) 작성된다는 사실에 의해 제공됩니다.
Git 저장소는 다음을 사용하여 정기적인 유지 보수가 필요합니다.git gc
(디스크 공간을 줄이고 성능을 향상시키기 위해) 요즘 Git는 자동으로 이를 수행합니다. (이 방법은 저장소를 더 잘 압축합니다.)
Mercurial(내가 이해하는 한)은 파일 로그에 파일의 기록을 저장합니다(이름 변경 추적과 같은 추가 메타데이터 및 일부 도우미 정보와 함께). 디렉토리 구조를 저장하기 위해 매니페스트라는 플랫 구조와 변경 집합(수정본)에 대한 정보를 저장하는 changelog라는 구조를 사용합니다.커밋 메시지와 0, 한 명 또는 두 명의 부모를 포함합니다.
Mercurial은 트랜잭션 저널을 사용하여 작업의 원자성을 제공하며, 작업이 실패하거나 중단된 후 정리할 파일을 잘라냅니다.Revlog는 추가 전용입니다.
Git의 저장소 구조와 Mercurial의 저장소 구조를 살펴보면 Git가 객체 데이터베이스(또는 콘텐츠 주소 파일 시스템)에 더 가깝다는 것을 알 수 있으며 Mercurial은 기존의 고정 필드 관계형 데이터베이스에 더 가깝다는 것을 알 수 있습니다.
차이점:
Git에서 트리 객체는 계층 구조를 형성하고 Mercurial 매니페스트 파일은 플랫 구조입니다.Git blob 개체는 파일의 내용 중 하나의 버전을 저장하고 Mercurial 파일 로그는 단일 파일의 전체 기록을 저장합니다(여기서 이름 변경과 관련된 복잡성을 고려하지 않는 경우).즉, Git가 Mercurial보다 빠를 수 있는 작업 영역, 동일하게 간주되는 다른 모든 작업 영역(예: 병합 또는 프로젝트 기록 표시), Mercurial이 Git보다 빠를 수 있는 영역(예: 패치 적용 또는 단일 파일의 기록 표시)이 서로 다릅니다.이 문제는 최종 사용자에게 중요하지 않을 수 있습니다.
Mercurial의 변경 로그 구조의 고정 레코드 구조 때문에, Mercurial의 커밋은 최대 두 개의 부모만 가질 수 있고, Git의 커밋은 두 개 이상의 부모를 가질 수 있습니다(이를 "octopus merge"라고 함).이론적으로는 문어 병합을 일련의 두 부모 병합으로 대체할 수 있지만 Mercurial 및 Git 저장소 간 변환 시 문제가 발생할 수 있습니다.
내가 알기로는 Mercurial에는 Git의 주석이 달린 태그(태그 객체)가 없습니다.주석이 달린 태그의 특별한 경우는 서명된 태그입니다(PGP/GPG 서명 포함). Mercurial에서 동등한 기능은 Mercurial과 함께 배포되는 GpgExtension을 사용하여 수행할 수 있습니다.Git에서처럼 Mercurial에서 비커밋 개체에 태그를 지정할 수는 없지만, 그것은 그다지 중요하지 않다고 생각합니다. (일부 Git 저장소는 태그가 지정된 BLOB를 사용하여 서명된 태그를 확인하는 데 사용하는 공개 PGP 키를 배포합니다.)
참조: 분기 및 태그
Git 참조(분기, 원격 추적 분기 및 태그)는 커밋의 DAG 외부에 상주합니다(필요한 경우).참조:refs/heads/
네임스페이스(로컬 분기)는 커밋을 가리키며 일반적으로 "git commit"에 의해 업데이트됩니다. 이러한 이름은 분기의 끝(헤드)을 가리킵니다.참조:refs/remotes/<remotename>/
네임스페이스(원격 검색 분기) 커밋할 지점, 원격 저장소의 분기를 따릅니다.<remotename>
"git fetch" 또는 이와 동등한 방법으로 업데이트됩니다.참조:refs/tags/
네임스페이스(이름 공간)는 일반적으로 커밋(경량 태그) 또는 태그 개체(이름 공간 및 서명된 태그)를 가리키며, 변경되지 않습니다.
태그
Mercurial에서는 태그를 사용하여 수정본에 영구 이름을 지정할 수 있습니다. 태그는 무시 패턴과 유사하게 저장됩니다.전체적으로 볼 수 있는 태그가 수정 버전 제어 방식으로 저장됨을 의미합니다..hgtags
파일을 저장합니다.이는 두 가지 결과를 초래합니다. 첫째, Mercurial은 모든 태그의 현재 목록을 가져오고 이러한 파일을 업데이트하기 위해 이 파일에 대한 특수 규칙을 사용해야 합니다(예: 현재 체크아웃되지 않은 버전의 파일에서 가장 최근에 커밋된 버전을 읽습니다). 둘째,새 태그를 다른 사용자/다른 리포지토리에 표시하려면 이 파일의 변경 사항을 커밋해야 합니다(제가 이해하는 바로는).
Mercurial은 또한 로컬 태그를 지원하며, 다음에 저장됩니다.hg/localtags
다른 사람이 볼 수 없는 것(물론 양도할 수 없음)
InGit 태그는 다른 객체(일반적으로 태그 객체, 즉 커밋에 대한 포인트)에 저장된 고정(일정한) 참조입니다.refs/tags/
네임스페이스입니다.기본적으로 수정기호 집합을 가져오거나 밀어 넣을 때 git는 가져오거나 밀어넣는 수정기호를 가리키는 태그를 자동으로 가져오거나 밀어넣습니다.그러나 가져오기 또는 푸시할 태그를 어느 정도 제어할 수 있습니다.
Git는 경량 태그(커밋을 직접 가리킴)와 주석이 달린 태그(선택적으로 PGP 서명을 포함하는 태그 메시지를 포함하는 태그 개체를 가리킴)를 약간 다르게 처리합니다. 예를 들어, 기본적으로 "git description"을 사용하여 커밋을 설명할 때 주석이 달린 태그만 고려합니다.
Git는 Mercurial에서 로컬 태그와 엄격하게 동등하지 않습니다.그럼에도 불구하고 Git Best Practice에서는 준비된 변경 사항을 푸시하고 다른 사용자가 복제 및 가져오기할 수 있는 별도의 공용 베어 저장소를 설정할 것을 권장합니다.즉, 누르지 않는 태그(및 분기)는 리포지토리에 비공개입니다.다른 한편으로는 다음과 같은 네임스페이스를 사용할 수도 있습니다.heads
,remotes
또는tags
,예를들면local-tags
로컬 태그의 경우.
개인적인 의견:태그는 수정기호 그래프 외부에 있으므로 수정기호 그래프 외부에 있어야 합니다(수정기호 그래프에 대한 포인터임).태그는 버전이 아닌 태그여야 하지만 전송할 수 있습니다.Mercurial이 파일을 무시하는 것과 유사한 메커니즘을 사용하는 것은 처리해야 한다는 것을 의미합니다..hgtags
특히(트리 내 파일은 전송할 수 있지만 일반적으로 버전이 지정됨) 또는 로컬 전용 태그(.hg/localtags
버전은 아니지만 전송할 수 없습니다.
나뭇가지
Git 로컬 분기(분기 팁 또는 분기 헤드)는 새 커밋을 성장시킬 수 있는 커밋에 대한 명명된 참조입니다.지점은 또한 활성 개발 라인, 즉 지점 팁에서 도달할 수 있는 모든 커밋을 의미할 수 있습니다.로컬 분기가 상주합니다.refs/heads/
네임스페이스이므로 'master' 분기의 정규화된 이름은 'refs/heads/master'입니다.
Git의 현재 분기(체크아웃된 분기 및 새 커밋이 이동할 분기를 의미)는 HEAD 참조에서 참조되는 분기입니다.HEAD가 기호 참조가 아닌 커밋을 직접 가리키도록 할 수 있습니다. 익명의 분기에 있는 이 상황을 분리 HEAD("git branch"는 사용자가 '(지점 없음)'에 있음을 나타냅니다.
Mercurial에는 익명 분기(분기 헤드)가 있으며, 책갈피 확장을 통해 책갈피를 사용할 수 있습니다.이러한 북마크 분기는 순수하게 로컬이며, 이러한 이름(버전 1.6까지)은 Mercurial을 사용하여 전송할 수 없습니다.rsync 또는 scp를 사용하여 다음을 복사할 수 있습니다..hg/bookmarks
파일을 원격 저장소에 저장합니다.사용할 수도 있습니다.hg id -r <bookmark> <url>
책갈피의 현재 팁에 대한 수정기호 ID를 가져옵니다.
1.6개의 책갈피를 밀거나 당길 수 있기 때문입니다.Bookmarks Extension 페이지에는 원격 리포지토리 작업 섹션이 있습니다.Mercurial에서는 북마크 이름이 글로벌하다는 점에서 차이가 있지만 Git에서는 'remote'의 정의가 원격 저장소의 이름에서 로컬 원격 추적 지점의 이름으로의 지점 이름 매핑을 설명합니다.refs/heads/*:refs/remotes/origin/*
mapping은 'mapping/master'의 원격 저장소에 있는 'master' 분기('refs/heads/master')의 상태를 찾을 수 있음을 의미합니다.
Mercurial은 명명된 분기라고도 하며, 분기 이름이 커밋(변경 집합)에 포함됩니다.이러한 이름은 글로벌(페치 시 전송됨)입니다.이러한 지점 이름은 changeset\u2019s 메타데이터의 일부로 영구적으로 기록됩니다.최신 Mercurial을 사용하면 "지정된 분기"를 닫고 분기 이름 기록을 중지할 수 있습니다.이 메커니즘에서 가지 끝은 즉시 계산됩니다.
Mercurial의 "이름이 붙은 가지"는 그것들이 그것들이기 때문에 대신 커밋 레이블이라고 불러야 한다고 생각합니다.이름이 지정된 분기에는 여러 팁(자녀가 없는 여러 커밋)이 있을 수 있으며, 수정사항 그래프의 여러 분리된 부분으로 구성될 수도 있습니다.
Git에는 Mercurial "임베디드 브랜치"와 동등한 것이 없습니다. 더욱이 Git의 철학은 브랜치가 일부 커밋을 포함한다고 말할 수는 있지만 커밋이 특정 브랜치에 속한다는 것을 의미하지는 않는다는 것입니다.
Mercurial 문서에서는 적어도 수명이 긴 분기(리포지토리 워크플로우당 단일 분기), 즉 복제를 통한 분기에 대해 별도의 클론(별도의 저장소)을 사용할 것을 제안합니다.
밀어넣기 중인 가지
기본적으로 머큐리얼은 모든 헤드를 푸시합니다.단일 분기(단일 헤드)를 푸시하려면 푸시할 분기의 팁 리비전을 지정해야 합니다.분기 팁은 리비전 번호(리포지토리 로컬), 리비전 식별자, 북마크 이름(리포지토리 로컬, 전송되지 않음) 또는 내장된 분기 이름(분기 이름)으로 지정할 수 있습니다.
제가 이해하기로는 머큐리얼 용어로 "이름이 지정된 분기"에 있는 것으로 표시된 커밋이 포함된 개정 범위를 푸시하면 푸시하는 저장소에 이 "이름이 지정된 분기"가 있을 것입니다.즉, 이러한 포함된 분기("이름 지정된 분기")의 이름이 지정된 리포지토리/프로젝트의 복제본과 관련하여 글로벌하다는 것을 의미합니다.
기본적으로(에 따라 다름)push.default
구성 변수) "git push" 또는 "git push <remote>" Git는 일치하는 분기를 푸시합니다. 즉, 원격 저장소에 이미 동일한 분기가 있는 로컬 분기만 푸시합니다.사용할 수 있습니다.--all
git-push 옵션("git push --all")을 사용하여 모든 분기를 푸시하고, "git push <remote> <branch>를 사용하여 지정된 단일 분기를 푸시할 수 있으며, "git push <remote> HEAD"를 사용하여 현재 분기를 푸시할 수 있습니다.
위의 모든 것은 Git가 어떤 분기를 통해 푸시할지 구성되지 않았다고 가정합니다.remote.<remotename>.push
구성 변수입니다.
가져오는 중인 가지
참고: 여기서는 Git 용어를 사용합니다. 여기서 "fetch"는 변경 사항을 로컬 작업에 통합하지 않고 원격 저장소에서 변경 사항을 다운로드하는 것을 의미합니다.이것이 바로 "git fetch
그리고 "hg pull
합니다.
Mercurial은 기본적으로 원격 저장소에서 모든 헤드를 가져오지만 "를 통해 가져올 분기를 지정할 수 있습니다.hg pull --rev <rev> <url>
또는 "hg pull <url>#<rev>
단일 분기를 얻기 위해.리비전 식별자, "이름 지정된 분기" 이름(변경 로그에 포함된 분기) 또는 책갈피 이름을 사용하여 <rev>를 지정할 수 있습니다.그러나 북마크 이름(최소한 현재)은 전송되지 않습니다.지정된 분기 수정사항은 모두 이전될 것입니다."hg pull"은 익명의 이름 없는 머리로 가져온 가지 끝을 저장합니다.
기본적으로 Git에서 ("git clone"에 의해 만들어진 'origin' 리모트와 "git remote add"를 사용하여 만들어진 리모트의 경우)"git fetch
(또는 "git fetch <remote>
") 원격 저장소에서 모든 분기를 가져옵니다.refs/heads/
네임스페이스) 및 저장 위치refs/remotes/
네임스페이스입니다.이는 예를 들어 원격 'origin'에 있는 'master'(전체 이름: 'refs/heads/master')라는 분기가 'origin/master' 원격 추적 분기(전체 이름: 'refs/remotes/origin/master')로 저장(저장)된다는 것을 의미합니다.
다음을 사용하여 Git에서 단일 분기를 가져올 수 있습니다.git fetch <remote> <branch>
Git는 요청된 분기를 FETCH_HEAD에 저장하며, 이는 Mercurial 이름 없는 헤드와 유사합니다.
이는 강력한 refspec Git 구문의 기본 사례의 예에 불과합니다. refspec을 사용하여 가져올 분기와 저장 위치를 지정 및/또는 구성할 수 있습니다.예를 들어 기본 "fetch all branch" 대소문자는 '+refs/heads/*:refs/remotes/origin/*' 와일드카드 refspec으로 표시되며, "fetch single branch"는 'refs/heads/<branch>:'의 약자입니다.참조 규격은 원격 리포지토리의 분기(refs) 이름을 로컬 참조 이름에 매핑하는 데 사용됩니다.그러나 Git와 효과적으로 작업하기 위해서는 refspec에 대해 (많이) 알 필요가 없습니다(주로 "git remote" 명령 덕분입니다).
개인적인 의견:저는 개인적으로 Mercurial의 "이름이 붙은 분기"(변경 세트 메타데이터에 브랜치 이름이 포함됨)는 특히 분산 버전 제어 시스템의 경우 글로벌 네임스페이스를 사용한 잘못된 설계라고 생각합니다.예를 들어, Alice와 Bob 모두 저장소에 'for-joe'라는 이름의 "지점 이름 지정"이 있는 경우를 예로 들어 보겠습니다.그러나 Joe의 저장소에서는 두 개의 분기가 단일 분기로 잘못 처리됩니다.그래서 지점 이름 충돌을 방지하기 위한 협약을 어떻게든 마련했습니다.이것은 Git에 문제가 없습니다. Joe의 저장소에서 Alice의 'for-joe' 브랜치는 'alice/for-joe'이고 Bob의 'bob/for-joe'입니다.또한 Mercurial Wiki에서 제기된 지점 ID 문제와 지점 이름 분리를 참조하십시오.
머큐리얼의 "북마크 지점"은 현재 코어 내 유통 메커니즘이 부족합니다.
차이점:
James Woodyatt와 Steve Losh가 답변에서 말했듯이 이 영역은 Mercurial과 Git의 주요 차이점 중 하나입니다.기본적으로 Mercurial은 용어로 "헤드"라고 불리는 익명의 경량 코드라인을 사용합니다.Git는 원격 저장소에 있는 지점의 이름을 원격 추적 지점의 이름에 매핑하기 위한 주입식 매핑과 함께 가벼운 이름의 분기를 사용합니다.분기 이름을 "강제적으로" 지정합니다(단, 이름이 지정되지 않은 단일 분기, 분리 HEAD라고 하는 상황 제외). 하지만 항목 분기 워크플로우와 같은 분기가 많은 워크플로우에서는 단일 저장소 패러다임에서 여러 분기를 의미하는 더 잘 작동한다고 생각합니다.
이름 수정본
Git에서는 여러 가지 이름 수정 방법이 있습니다(예: git rev-parse manpage 입력).
- 전체 SHA1 개체 이름(40바이트 16진수 문자열) 또는 저장소 내에서 고유한 하위 문자열
- 기호 참조 이름(예: 'master'('master' 분기 참조), 'v1.5.0'(태그 참조) 또는 'origin/next'(원격 추적 분기 참조)
- 접미사
^
revision 매개 변수는 커밋 개체의 첫 번째 부모를 의미합니다.^n
병합 커밋의 n번째 상위 항목을 의미합니다.접미사~n
revision parameter는 직선 첫 번째 부모 라인에 있는 커밋의 n번째 조상을 의미합니다.이러한 접미사를 결합하여 기호 참조에서 경로를 따라 수정 지정자를 형성할 수 있습니다(예: 'pu~3^2~3'). - "git description"(예: 가장 가까운 태그)의 출력. 선택적으로 대시와 여러 커밋이 뒤따르고 대시, 'g' 및 약어 개체 이름이 뒤따릅니다(예: 'v1.6.5.1-75-g5bf8097').
여기에 언급되지 않은 reflog와 관련된 개정 지정자도 있습니다.Git에는 commit, tag, tree 또는 blob의 각 개체에 SHA-1 식별자가 있습니다. 예를 들어 'next:설명서' 또는 '다음:README'는 지정된 리비전에서 트리(디렉토리) 또는 BLOB(파일 내용)를 나타냅니다.
Mercurial에는 변경 세트의 이름을 지정하는 여러 가지 방법이 있습니다(예: hgmanpage에서 설명됨).
- 일반 정수는 수정 번호로 처리됩니다.리비전 번호는 지정된 리포지토리의 로컬 번호이며, 다른 리포지토리에서는 다를 수 있습니다.
- 음의 정수는 팁에서 순차적 오프셋으로 처리되며 -1은 팁을 나타내고 -2는 팁 이전의 수정을 나타냅니다.또한 저장소의 로컬 위치이기도 합니다.
- 고유 리비전 식별자(40자리 16진수 문자열) 또는 고유 접두사.
- 태그 이름(지정된 리비전과 관련된 기호 이름), 북마크 이름(확장자: 지정된 헤드와 관련된 기호 이름, 리포지토리에 로컬로 연결된 기호 이름) 또는 "이름 지정된 분기"(커밋 레이블, "이름 지정된 분기"에 의해 지정된 리비전은 지정된 커밋 레이블의 팁(자녀 없음 커밋),이러한 팁이 둘 이상 있는 경우 가장 큰 개정 번호)
- 예약된 이름 "tip"은 항상 최신 버전을 식별하는 특수 태그입니다.
- 예약된 이름 "null"은 null 수정본을 나타냅니다.
- 예약된 이름 "."은 작업 디렉터리 상위를 나타냅니다.
차이점.
위의 목록을 비교해 보면 알 수 있듯이 Mercurial은 저장소에 대한 로컬 버전 번호를 제공하는 반면 Git은 제공하지 않습니다.반면에 Mercurial은 (적어도 Parentrevspec Extension 없이) 리포지토리에 로컬인 'tip'(현재 분기)에서만 상대 오프셋을 제공하는 반면 Git는 팁에서 커밋 팔로잉을 지정할 수 있습니다.
가장 최근의 개정판은 Git에서 HEAD, Mercurial에서 "tip"으로 명명되었습니다. Git에서는 null 개정판이 없습니다.Mercurial과 Git 모두 많은 루트를 가질 수 있습니다(둘 이상의 부모 없는 커밋을 가질 수 있습니다. 이는 보통 이전에 별도의 프로젝트가 참여했기 때문입니다.
참고 항목:Eliza's Blog(신간)에 다양한 종류의 개정 지정자 기사가 있습니다.
개인적인 의견:개정 번호가 과대평가되었다고 생각합니다(적어도 분산 개발 및/또는 비선형/분기 이력에 대해서는).첫째, 분산 버전 제어 시스템의 경우 저장소에 로컬이거나 중앙 번호 지정 기관으로 특정한 방식으로 일부 저장소를 처리해야 합니다.둘째로, 더 긴 역사를 가진 더 큰 프로젝트는 5자리 범위의 수정본 수를 가질 수 있으므로 6-7자 수정본 식별자로 단축된 것보다 약간의 이점만 제공하고 수정본은 부분적으로만 정렬됩니다(여기서 수정본 n 및 n+1이 부모 및 자식일 필요는 없음).
수정 범위
Git에서 개정 범위는 위상학적입니다.흔히 볼 수 있는A..B
선형 역사에서 A로 시작하는 개정 범위(그러나 A를 제외함)와 B로 끝나는 개정 범위(즉, 범위가 아래에서 열려 있음)를 의미하는 구문은 다음과 같은 약어("통사당")입니다.^A B
이는 기록 순회 명령의 경우 A에서 도달할 수 있는 커밋을 제외하고 B에서 도달할 수 있는 모든 커밋을 의미합니다.이는 다음과 같은 것을 의미합니다.A..B
범위는 A가 B의 조상이 아니더라도 완전히 예측 가능하며 매우 유용합니다.A..B
즉, A와 B의 공통 조상(합병 기준)에서 수정본 B까지의 수정본 범위를 의미합니다.
수은 개정 범위는 개정 번호 범위를 기반으로 합니다.범위는 다음을 사용하여 지정됩니다.A:B
Git 범위와 반대되는 구문은 닫힌 간격으로 작동합니다.또한 범위 B:A는 역순으로 범위 A:B이며, Git에서는 그렇지 않습니다(단, 아래 참고 사항 참조).A...B
구문)을 선택합니다.그러나 이러한 단순성에는 대가가 따릅니다. 리비전 범위 A:B는 A가 B의 조상이거나 선형 이력이 있는 경우에만 의미가 있습니다. 그렇지 않으면(리비전 번호가 저장소에 로컬이기 때문에) 범위를 예측할 수 없고 결과는 저장소에 로컬입니다.
이것은 새로운 위상 수정 범위를 가진 Mercurial 1.6에서 수정되었습니다. 여기서 'A..B'(또는 'A::B')는 X의 후손이자 Y의 조상인 변화 집합으로 이해됩니다.이것은, 제 생각에, '--조상 경로 A..'와 같습니다.Git에서 B'.
Git에도 표기법이 있습니다.A...B
수정사항의 대칭적 차이에 대한 것입니다.A B --not $(git merge-base A B)
즉, A 또는 B에서 도달할 수 있는 모든 커밋을 의미하지만 두 커밋 모두에서 도달할 수 있는 모든 커밋은 제외합니다(공동 조상에서 도달할 수 있음).
이름 바꾸기
Mercurial은 파일 이름 변경을 처리하기 위해 이름 변경 추적을 사용합니다.즉, 파일 이름이 변경된 사실에 대한 정보는 커밋 시간에 저장됩니다. Mercurial에서는 이 정보가 파일 로그(파일 revlog) 메타데이터의 "향상된 diff" 형식으로 저장됩니다.결과적으로 당신은 사용해야 합니다.hg rename
/hg mv
아니면 도망치는 걸 기억해야 해요hg addremove
유사성 기반 이름 바꾸기 탐지를 수행합니다.
Git는 파일 이름 변경을 처리하기 위해 이름 변경 탐지를 사용한다는 점에서 버전 제어 시스템 중 유일합니다.즉, 파일 이름이 변경된 사실은 병합을 수행할 때 또는 디프를 표시할 때(요청/구성된 경우) 필요할 때 감지됩니다.이는 탐지 알고리즘 이름 변경을 개선할 수 있으며 커밋 시 고정되지 않는다는 장점이 있습니다.
Git와 Mercurial 모두 다음을 사용해야 합니다.--follow
단일 파일의 기록을 표시할 때 이름을 변경하는 옵션입니다.둘 다 파일의 기록을 줄 단위로 표시할 때 이름 바꾸기를 따를 수 있습니다.git blame
/hg annotate
.
깃더git blame
명령은 코드 이동을 추적할 수 있으며, 코드 이동이 건전한 파일 이름 변경의 일부가 아닐지라도 한 파일에서 다른 파일로 코드를 이동(또는 복사)할 수 있습니다.제가 알기로는 이 기능은 Git의 고유한 기능입니다(2009년 10월 작성 당시).
네트워크 프로토콜
Mercurial과 Git 모두 동일한 파일 시스템의 리포지토리로 가져오기 및 푸시를 지원합니다. 여기서 리포지토리 URL은 리포지토리에 대한 파일 시스템 경로일 뿐입니다.또한 두 제품 모두 번들 파일에서 가져오기를 지원합니다.
SSH 및 HTTP 프로토콜을 통해 가져오기 및 푸시를 지원합니다.SSH의 경우 대상 시스템에 액세스할 수 있는 셸 계정과 설치/사용 가능한 hg 복사본이 필요합니다.HTTP 액세스의 경우hg-serve
또는 Mercurial CGI 스크립트를 실행해야 하며 서버 시스템에 Mercurial을 설치해야 합니다.
Git는 원격 저장소에 액세스하는 데 사용되는 두 가지 프로토콜을 지원합니다.
- SSH 및 사용자 지정 git:// 프로토콜을 통한 액세스를 포함하는 "스마트" 프로토콜(by
git-daemon
), 서버에 GIT를 설치해야 합니다.이러한 프로토콜의 교환은 클라이언트와 서버가 공통적으로 어떤 개체를 가지고 있는지 협상한 다음 팩 파일을 생성하고 전송하는 것으로 구성됩니다.모던 Git에는 "스마트" HTTP 프로토콜 지원이 포함되어 있습니다. - HTTP 및 FTP(Fetching 전용)와 HTTPS(WebDAV를 통한 푸시용)를 포함하는 "dumb" 프로토콜은 서버에 git를 설치할 필요가 없지만 저장소에 생성된 추가 정보가 있어야 합니다.
git update-server-info
(일반적으로 후크에서 실행됨).교환은 클라이언트가 커밋 체인을 걷고 필요에 따라 느슨한 개체와 팩 파일을 다운로드하는 것으로 구성됩니다.단점은 엄격하게 요구되는 것보다 더 많이 다운로드된다는 것입니다(예: 코너의 경우에는 하나의 팩 파일만 있는 경우에는 몇 개의 수정사항만 가져오는 경우에도 전체적으로 다운로드됩니다). 그리고 완료하는 데 많은 연결이 필요할 수 있습니다.
확장: 스크립트 가능성 대 확장(플러그인)
Mercurial은 Python에서 구현되며 성능을 위해 일부 코어 코드는 C로 작성됩니다.추가 기능을 추가하는 방법으로 확장자(플러그인)를 작성하기 위한 API를 제공합니다."북마크 분기" 또는 서명 수정본과 같은 일부 기능은 Mercurial과 함께 배포되는 확장으로 제공되며 이 기능을 켜야 합니다.
Git는 C, Perl 및 셸 스크립트에서 구현됩니다.Git는 스크립트에 사용하기에 적합한 많은 낮은 수준의 명령(플럼핑)을 제공합니다.새로운 기능을 도입하는 일반적인 방법은 Perl 또는 Shell 스크립트로 작성하고 사용자 인터페이스가 안정화되면 성능, 휴대성, 셸 스크립트의 경우 코너 케이스를 피하기 위해 C로 다시 작성하는 것입니다(이 절차를 builtinification이라고 함).
Git는 [리포지토리] 형식과 [네트워크] 프로토콜에 의존하고 이를 기반으로 구축됩니다.언어 바인딩 대신 다른 언어로 Git의 (부분적 또는 완전한) 재구현이 있습니다(일부는 부분적으로 재구현되고 일부는 git 명령어를 둘러싼 래퍼입니다).JGit(Java, EGit, Eclipse Git Plugin에서 사용), Grit(Ruby), Dulwich(Python), git#(C#).
TL;DR
이 두 개의 비디오를 보면 시스템이 어떤 점에서 비슷하거나 다른지 알 수 있을 것입니다.
리누스 토발스 온 깃(http://www.youtube.com/watch?v=4XpnKHJAok8)
Bryan O'Sullivan on Mercurial (http://www.youtube.com/watch?v=JExtkqzEoHY) )
두 가지 모두 디자인은 매우 비슷하지만 구현은 매우 다릅니다.
머큐리얼을 사용합니다.제가 Git를 이해하는 한, Git이 다른 한 가지 주요한 점은 파일 자체가 아니라 파일의 내용을 추적한다는 것입니다.리누스는 만약 당신이 어떤 함수를 한 파일에서 다른 파일로 옮기면, Git이 당신에게 그 단일 함수의 역사를 말해줄 것이라고 말합니다.
그들은 또한 Git가 HTTP보다 느리지만 자체 네트워크 프로토콜과 서버를 가지고 있다고 말합니다.
Git은 Mercurial보다 SVN 씩 클라이언트로 더 잘 작동합니다.SVN 서버에 대해 풀 앤 푸시를 수행할 수 있습니다.이 기능은 Mercurial에서 아직 개발 중입니다.
Mercurial과 Git 모두 매우 좋은 웹 호스팅 솔루션(BitBucket 및 GitHub)을 사용할 수 있지만 Google 코드는 Mercurial만 지원합니다.그런데, 그들은 어떤 것을 지원할지 결정하기 위해 Mercurial과 Git를 매우 상세하게 비교했습니다(http://code.google.com/p/support/wiki/DVCSAnalysis) .그것은 많은 좋은 정보를 가지고 있습니다.
저는 둘 다 꽤 정기적으로 사용합니다.주요 기능적 차이는 Git 및 Mercurial 이름이 저장소 내에서 분기하는 방식에 있습니다.Mercurial을 사용하면 지점 이름이 복제되고 변경 세트와 함께 당겨집니다.Mercurial의 새 분기에 변경 사항을 추가하고 다른 리포지토리에 푸시하면 분기 이름이 동시에 푸시됩니다.따라서 지점 이름은 Mercurial에서 거의 전역 이름이며, 로컬 전용 경량 이름을 사용하려면 책갈피 확장명을 사용해야 합니다(원하는 경우, Mercurial은 기본적으로 익명 경량 코드라인을 사용하며, 용어로는 "헤드"라고 합니다).Git에서는 지점 이름과 원격 지점에 대한 주입식 매핑이 로컬로 저장되므로 사용자가 명시적으로 관리해야 합니다. 즉, 이러한 방법을 알고 있어야 합니다.이것은 Git가 Mercurial보다 배우고 사용하기 어렵다는 평판을 얻는 곳입니다.
다른 사람들이 여기서 주목할 것처럼, 많은 작은 차이점들이 있습니다.가지에 있는 것은 큰 차별화 요소입니다.
모든 인터넷 커뮤니티에서 Mercurial이 더 쉽다는 것을 읽은 후(모든 인터넷 커뮤니티에서 의견이 나온 후) Git 및 Mercurial과 함께 일하기 시작했을 때 Git이 비교적 간단하게 적응할 수 있다고 느꼈습니다(나는 명령 줄에서 작업할 때 TortoeHg와 함께 Mercurial과 함께 시작했습니다).주로 git 명령어가 나에 따라 적절하게 이름 지어졌고 수가 적었기 때문입니다.Mercurial은 고유한 작업을 수행하는 각 명령에 대해 서로 다른 이름을 지정하는 반면 Git 명령은 상황에 따라 다목적이 될 수 있습니다(예:checkout
당시에는 Git이 더 어려웠지만, 지금은 그 차이가 거의 없습니다.YMMV.. TorothyHg와 같은 좋은 GUI 클라이언트를 사용하면 Mercurial로 작업하는 것이 훨씬 쉬웠고 약간 혼란스러운 명령을 기억할 필요가 없었습니다.동일한 작업에 대한 모든 명령이 어떻게 달라졌는지 자세히 설명하지는 않겠지만, 여기 두 가지 포괄적인 목록이 있습니다. 하나는 머큐리얼의 자체 사이트에서, 두 번째는 위키브에서입니다.
╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Git ║ Mercurial ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull ║ hg pull -u ║
║ git fetch ║ hg pull ║
║ git reset --hard ║ hg up -C ║
║ git revert <commit> ║ hg backout <cset> ║
║ git add <new_file> ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.) ║
║ git add <file> ║ Not necessary in Mercurial. ║
║ git add -i ║ hg record ║
║ git commit -a ║ hg commit ║
║ git commit --amend ║ hg commit --amend ║
║ git blame ║ hg blame or hg annotate ║
║ git blame -C ║ (closest equivalent): hg grep --all ║
║ git bisect ║ hg bisect ║
║ git rebase --interactive ║ hg histedit <base cset> (Requires the HisteditExtension.) ║
║ git stash ║ hg shelve (Requires the ShelveExtension or the AtticExtension.) ║
║ git merge ║ hg merge ║
║ git cherry-pick <commit> ║ hg graft <cset> ║
║ git rebase <upstream> ║ hg rebase -d <cset> (Requires the RebaseExtension.) ║
║ git format-patch <commits> ║ hg email -r <csets> (Requires the PatchbombExtension.) ║
║ and git send-mail ║ ║
║ git am <mbox> ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.) ║
║ git checkout HEAD ║ hg update ║
║ git log -n ║ hg log --limit n ║
║ git push ║ hg push ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝
Git는 모든 버전의 커밋된 파일에 대한 레코드를 내부적으로 저장하는 반면 Hg는 설치 공간이 더 작을 수 있는 변경 세트만 저장합니다.Git은 Hg와 비교하여 역사를 바꾸는 것을 더 쉽게 만들지만, 다시 말해 Hate-it-or-Love-it 기능입니다.전자는 Hg, 후자는 Git를 좋아합니다.
Hg에서 내가 그리워하는 것은 Git의 서브모듈 기능입니다.HG는 서브레포스를 가지고 있지만 그것은 정확히 Git 서브모듈이 아닙니다.
두 가지를 중심으로 한 생태계도 선택에 영향을 미칠 수 있습니다.깃은 더 인기가 있어야 합니다. 깃허브는 깃허브이고 머큐리얼은 비트버킷이고 머큐리얼은 터틀Hg를 가지고 있습니다. 저는 깃허브와 동등한 것을 본 적이 없습니다.
각각의 장점과 단점이 있는데, 그 중 어느 것도 지지 않을 것입니다.
머큐리얼은 거의 완전히 파이썬으로 쓰여 있습니다.Git의 코어는 C로 작성되며(그리고 Mercurial보다 더 빨라야 함) 도구는 sh, perl, tcl로 작성되며 표준 GNU 유틸리티를 사용합니다.따라서 이러한 모든 유틸리티와 인터프리터를 포함하지 않는 시스템(예: Windows)으로 가져와야 합니다.
두 지원 모두 SVN과 함께 작동하지만, AFAIK svn 지원이 Windows에서 잘못되었음에도 불구하고(아마도 나는 운이 나빴을 것이다/레임일 것이다, 누가 알겠는가).Git와 Mercurial 간의 상호 운용을 가능하게 하는 확장 기능도 있습니다.
Mercurial은 Visual Studio와 완벽하게 통합되어 있습니다.지난번에 확인했을 때 Git용 플러그인은 작동하고 있었지만 매우 느렸습니다.
기본 명령 집합(init, clone, add, status, commit, push, pull 등)은 매우 유사합니다.따라서 기본 워크플로우도 동일합니다.또한 거북이도 있습니다.둘 다를 위한 SVN 같은 클라이언트입니다.
Mercurial용 확장자는 python으로 작성할 수 있으며(놀랍지 않습니다!), 실행 가능한 형식(실행 가능한 이진, 셸 스크립트 등)으로 작성할 수 있습니다.어떤 확장들은 미친 듯이 강력해요, 마치.git bisect
.
좋은 Windows 지원이 필요한 경우 Mercurial을 선호할 수 있습니다.TorothyHg(Windows 탐색기 플러그인)는 사용하기 쉬운 그래픽 인터페이스를 다소 복잡한 도구에 제공합니다.여기에 있는 것처럼 Visual Studio 플러그인도 사용할 수 있습니다.하지만 지난번에 시도했을 때 Windows에서 SVN 인터페이스가 제대로 작동하지 않았습니다.
명령줄 인터페이스가 괜찮다면 Git을 추천합니다.기술적인 이유가 아니라 전략적인 이유 때문입니다.git의 채택률이 훨씬 높습니다.얼마나 많은 유명한 오픈 소스 프로젝트가 cvs/svn에서 Mercurial로 전환되고 있는지 그리고 얼마나 많은 프로젝트가 Git로 전환되는지 확인하십시오.Mercurial 호스팅과 비교하여 Git 지원을 통해 찾을 수 있는 코드/프로젝트 호스팅 공급자 수를 확인하십시오.
얼마 전부터 스콧 샤콘의 게시물을 확인해 보세요.
저는 깃이 "더 복잡하다"는 평판을 가지고 있다고 생각하지만, 제 경험으로는 필요 이상으로 복잡하지 않습니다.IMO, git 모델은 이해하기 훨씬 쉽습니다(태그에 커밋 포함, 0개 이상의 상위 커밋에 대한 포인터 포함) 트리에는 블롭 및 기타 트리가 포함되어 있습니다...완료됨).
기트가 수은보다 더 혼란스럽지 않다는 것은 제 경험뿐만이 아닙니다.저는 그 문제에 대해 스콧 샤콘의 블로그 게시물을 다시 읽는 것을 추천합니다.
저는 현재 직장에서 Git를 1년 조금 넘게 사용했고, 그 이전 직장에서는 Mercurial을 1년 조금 넘게 사용했습니다.나는 사용자의 관점에서 평가를 제공할 것입니다.
첫째, 둘 다 분산 버전 제어 시스템입니다.분산 버전 제어 시스템은 기존 버전 제어 시스템에서 사고 방식을 변경해야 하지만, 일단 이해하면 여러 면에서 훨씬 더 잘 작동합니다.이러한 이유로, 나는 Git와 Mercurial 둘 다 Subversion, Perforce 등보다 훨씬 우월하다고 생각합니다.분산 버전 제어 시스템과 기존 버전 제어 시스템의 차이는 Git와 Mercurial의 차이보다 훨씬 큽니다.
그러나 Git와 Mercurial 사이에는 각각의 사용 사례의 하위 집합에 더 적합하게 만드는 상당한 차이가 있습니다.
머큐리얼은 배우기가 더 쉽습니다.몇 주 동안 Mercurial을 사용한 후에는 설명서나 노트를 거의 참조하지 않아도 되는 지경에 이르렀습니다. Git를 사용하여 1년 동안 정기적으로 노트를 참조해야 합니다.Git은 상당히 더 복잡합니다.
이것은 부분적으로 머큐리얼이 그저 단순한 청소기이기 때문입니다.Mercurial에서 수동으로 분기할 필요가 거의 없습니다. Mercurial은 필요할 때 자동으로 익명 분기를 생성합니다.수은 명명법은 더 직관적입니다. Git를 사용하는 것처럼 "fetch"와 "pull"의 차이에 대해 걱정할 필요가 없습니다.머큐리얼은 좀 덜 버기 때문입니다.Git 및 Mercurial이 모두 있는 플랫폼에서 프로젝트를 푸시할 때 문제를 일으키는 파일 이름 대소문자 구분 문제가 있습니다. 마지막으로 확인한 결과 Git에서 수정되지 않은 상태에서 얼마 전에 Mercurial에서 수정되었습니다.당신은 Mercurial에게 파일 이름 변경에 대해 말할 수 있습니다. Git을 사용하면 이름 변경을 자동으로 감지하지 못하면 이름 변경을 추적할 수 없습니다.
그러나 Git의 추가적인 복잡성의 또 다른 이유는 추가 기능과 전력을 지원하는 데 상당 부분이 필요하기 때문입니다.네, Git에서 분기를 처리하는 것은 더 복잡하지만, 반면에, 일단 분기를 갖게 되면, Mercurial에서 사실상 불가능한 해당 분기로 작업을 수행하는 것은 그리 어렵지 않습니다.분기의 기본 재배치는 다음 중 하나입니다. 분기할 때 트렁크의 상태가 아니라 분기의 기본이 현재 트렁크의 상태가 되도록 분기를 이동할 수 있습니다. 동일한 코드 기반에서 작업하는 사용자가 많을 때 트렁크에 대한 각 푸시가 순차적으로 나타날 수 있으므로 버전 기록을 크게 단순화할 수 있습니다.얽히기보다는마찬가지로 분기의 여러 커밋을 단일 커밋으로 축소하는 것이 훨씬 쉬우며, 이는 버전 제어 기록을 깨끗하게 유지하는 데 다시 도움이 될 수 있습니다. 이상적으로는 기능에 대한 모든 작업이 트렁크에서 단일 커밋으로 나타나 기능을 개발하는 동안 개발자가 수행한 모든 사소한 커밋과 하위 브랜치를 대체할 수 있습니다.
궁극적으로 Mercurial과 Git 사이의 선택은 동시에 작업하는 사람의 수로 측정되는 버전 제어 프로젝트의 크기에 따라 달라져야 한다고 생각합니다.예를 들어, 단일 단일 단일 웹 애플리케이션을 작업하는 그룹이 12명 이상인 경우 Git의 더욱 강력한 지점 관리 툴을 사용하면 프로젝트에 훨씬 적합합니다.한편, 한 번에 한 명 또는 두 명의 개발자가 한 구성 요소에 대해 작업하는 이기종 분산 시스템을 개발하는 경우 각 구성 요소 프로젝트에 대해 Mercurial 저장소를 사용하면 저장소 관리 오버헤드를 줄이면서 개발을 보다 원활하게 진행할 수 있습니다.
결론: 거대한 단일 애플리케이션을 개발하는 대규모 팀이 있다면 Git을 사용하십시오. 개별 애플리케이션이 규모가 작고 애플리케이션의 크기가 아닌 수에 따라 규모가 결정되는 경우 Mercurial을 사용하십시오.
DVCS 자체와는 전혀 관련이 없는 한 가지 차이점이 있습니다.
Git은 C 개발자들에게 매우 인기가 있는 것 같습니다.Git는 리눅스 커널의 사실상의 저장소이며 이것이 C 개발자들에게 인기 있는 이유일 수 있습니다.특히 Linux/Unix 환경에서만 작업할 수 있는 여유가 있는 사용자의 경우에는 더욱 그렇습니다.
자바 개발자들은 Git보다 Mercurial을 선호하는 것 같습니다.두 가지 이유가 있을 수 있습니다.하나는 JDK 자체를 포함하여 수많은 대규모 Java 프로젝트가 Mercurial에서 호스팅된다는 것입니다.다른 하나는 Mercurial의 구조와 깨끗한 문서가 Java 캠프에서 오는 사람들에게 어필하는 반면, 그러한 사람들은 Git이 일관되지 않은 wrt 명령 이름을 지정하고 문서화가 부족하다고 생각한다는 것입니다.저는 그것이 사실이라고 말하는 것이 아닙니다. 제 말은 사람들이 그들의 일상적인 서식지에서 무언가에 익숙해졌고 그들은 그 중에서 DVCS를 선택하는 경향이 있다는 것입니다.
파이썬 개발자들은 거의 전적으로 Mercurial을 선호한다고 생각합니다.사실 Mercurial이 Python을 기반으로 한다는 사실 외에는 합리적인 이유가 없습니다. (저도 Mercurial을 사용하는데 왜 사람들이 DVCS의 구현 언어에 대해 소란을 피우는지 정말 이해할 수 없습니다.저는 파이썬을 한 마디도 이해하지 못합니다. 그리고 파이썬을 기반으로 하는 어딘가에 나열되어 있다는 사실이 없었다면 저는 몰랐을 것입니다.)
하나의 DVCS가 다른 언어보다 더 잘 어울린다고 말할 수는 없다고 생각하기 때문에 선택해서는 안 됩니다.그러나 실제로 사람들은 커뮤니티의 일부로 가장 많이 노출되는 DVCS를 기준으로 선택합니다.
(아니요, 위의 주장을 뒷받침할 사용 통계가 없습니다.그것은 모두 나 자신의 주관성에 기초합니다)
언급URL : https://stackoverflow.com/questions/1598759/git-and-mercurial-compare-and-contrast
'programing' 카테고리의 다른 글
Git, 저장소에 관련 없는 분기를 도입하는 간단한 방법이 있습니까? (0) | 2023.05.09 |
---|---|
Xcode에는 코드 자동 포맷 기능이 있습니까? (0) | 2023.05.09 |
.vmsx 파일이 언제 필요하며 어떻게 사용하시겠습니까? (0) | 2023.05.09 |
HTML에 대한 #지역 코드가 있습니까? (0) | 2023.05.09 |
npm 패키지의 로컬 설치를 위한 사용자 지정 위치를 설정하는 방법은 무엇입니까? (0) | 2023.05.09 |