힘내와 머큐리얼-비교 및 대조
한동안 나는 개인 프로젝트에 서브 버전을 사용하고있다.
점점 더 Git과 Mercurial, 그리고 DVCS에 대한 좋은 소식을 계속 듣고 있습니다.
DVCS 전체에 소용돌이를 드리고 싶지만 어느 옵션에도 익숙하지 않습니다.
Mercurial과 Git의 차이점은 무엇입니까?
참고 : 나는 어느 것이 "가장 좋은지"또는 어떤 것을 시작해야하는지 찾으려고 하지 않습니다 . 나는 주로 구현과 철학 측면에서 어떻게 다른지 알고 싶어하기 때문에 비슷한 부분과 다른 부분을 주로 찾고 있습니다.
면책 조항 : 나는 Git을 사용하고 git 메일 링리스트에서 Git 개발을 따르고 심지어 Git (주로 gitweb)에 약간 기여합니다. 나는 설명서와 FreeNode의 #revctrl IRC 채널에 대한 토론에서 Mercurial을 알고 있습니다.
이 글을 위해 Mercurial에 대한 도움을 주신 #mercurial IRC 채널의 모든 사람들에게 감사합니다
요약
여기에 MarkMark의 PHPMarkdown / MultiMarkdown / Maruku 확장과 같은 테이블에 대한 구문이 있으면 좋을 것입니다.
- 리포지토리 구조 : Mercurial에서는 문어 병합 (부모가 둘 이상) 또는 커밋되지 않은 객체에 태그를 지정할 수 없습니다.
- 태그 : Mercurial은
.hgtags
리포지토리 당 태그에 대한 특수 규칙이있는 버전이 지정된 파일을 사용 하며 로컬 태그도 지원합니다.hg/localtags
. Git에서 태그는refs/tags/
네임 스페이스에 상주하며 기본적으로 페치시 자동 추적되며 명시적인 푸시가 필요합니다. - 지점 : Mercurial의 기본 워크 플로우는 익명 헤드를 기반 으로합니다 . Git은 가벼운 이름의 브랜치를 사용 하고 원격 저장소의 브랜치를 따르는 특별한 종류의 브랜치 ( 원격 추적 브랜치 )가 있습니다.
- 수정 명명 및 범위 : 의욕 제공 버전 번호 , 로컬 저장소, 염기 상대적인 변경 (팁으로부터 계산, 즉 현재 브랜치) 및 이에 대한 수정 범위 지역 번호를; Git은 브랜치 팁을 기준으로 개정을 참조하는 방법을 제공하며 개정 범위는 토폴로지입니다 (개정 그래프를 기반으로 함)
- Mercurial은 이름 변경 추적을 사용 하고 Git은 이름 변경 감지 를 사용 하여 파일 이름 변경을 처리합니다.
- 네트워크 : Mercurial은 SSH 및 HTTP "스마트"프로토콜 및 정적 HTTP 프로토콜을 지원합니다. 최신 Git은 SSH, HTTP 및 GIT "스마트"프로토콜 및 HTTP (S) "덤"프로토콜을 지원합니다. 둘 다 오프라인 전송을위한 번들 파일을 지원합니다.
- Mercurial은 확장 (플러그인) 및 설정된 API를 사용합니다. Git은 스크립팅 기능 과 확립 된 형식을 가지고 있습니다.
Git과 Mercurial과 다른 점이 몇 가지 있지만 비슷한 점이 있습니다. 두 프로젝트 모두 서로 아이디어를 빌립니다. 예를 들어 hg bisect
Mercurial의 명령 (이전의 이등분 확장 )은 git bisect
Git의 명령에서 영감을 얻은 반면 아이디어는 git bundle
에서 영감을 얻었습니다 hg bundle
.
리포지토리 구조, 수정본 저장
Git에는 파일의 내용을 포함하는 blob 객체 , 파일 이름 및 파일 권한의 관련 부분 (파일에 대한 실행 권한, 심볼릭 링크)을 포함하여 디렉토리 구조를 저장하는 계층 적 트리 객체 인 객체 데이터베이스에 Git에는 4 가지 유형의 객체가 있습니다. , 소유권 정보가 포함 된 커밋 객체, 커밋 (프로젝트의 최상위 디렉토리의 트리 객체를 통해)으로 표시되는 개정시 저장소 상태의 스냅 샷에 대한 포인터 및 0 개 이상의 상위 커밋에 대한 참조 및 다른 객체를 참조하고 할 수있는 태그 객체 PGP / GPG를 사용하여 서명하십시오.
: 자식 객체를 저장하는 두 가지 방법이 사용 느슨한 각 객체 (그 파일이 추기 및 변성되지 않습니다)는 별도의 파일에 저장되는 형식과 압축 많은 개체 델타 압축 된 하나의 파일에 저장되는 형식. 작업의 원자 성은 객체를 작성한 후 새 객체에 대한 참조가 (원자 적으로 create + rename trick을 사용하여) 작성된다는 사실에 의해 제공됩니다.
Git 리포지토리에는 git gc
(디스크 공간을 줄이고 성능을 향상시키기 위해) 정기적 인 유지 관리가 필요 하지만 현재는 Git에서 자동으로 수행합니다. (이 방법은 리포지토리를 더 잘 압축합니다.)
Mercurial (내가 이해하는 한)은 파일의 기록을 파일 로그에 저장합니다 (이름 변경 추적과 같은 추가 메타 데이터 및 일부 도우미 정보와 함께). 디렉토리 구조를 저장하기 위해 manifest 라는 플랫 구조를 사용 하고 커밋 메시지 및 0, 1, 2 개의 부모를 포함하여 변경 세트 (개정)에 대한 정보를 저장하는 changelog 구조 를 사용합니다.
Mercurial은 트랜잭션 저널 을 사용하여 작업의 원 자성을 제공하며, 실패하거나 중단 된 작업 후 파일을 정리하여 파일을 잘라 냅니다. Revlog는 추가 전용입니다.
Git과 Mercurial의 저장소 구조를 살펴보면 Git은 객체 데이터베이스 (또는 컨텐츠 주소가 지정된 파일 시스템)와 비슷하고 Mercurial은 기존의 고정 필드 관계형 데이터베이스와 비슷하다는 것을 알 수 있습니다.
차이점 :
Git에서 트리 객체는 계층 구조를 형성합니다 . Mercurial 매니페스트 파일에서 플랫 구조입니다. Git Blob 객체 에는 파일 내용의 한 버전 이 저장 됩니다. Mercurial의 filelog 에는 단일 파일의 전체 기록이 저장 됩니다 (여기서 이름을 바꾸는 합병증을 고려하지 않은 경우). 즉, Git이 Mercurial보다 빠른 운영 영역, 병합 또는 프로젝트 기록 표시와 같이 동등한 것으로 간주되는 다른 모든 영역 및 패치 적용 또는 표시와 같은 Mercurial이 Git보다 빠른 영역이 있음을 의미합니다. 단일 파일의 기록).이 문제는 최종 사용자에게는 중요하지 않을 수 있습니다.
Mercurial 변경 기록 구조의 고정 레코드 구조로 인해 Mercurial의 커밋은 최대 두 명의 부모 만 가질 수 있습니다 . Git의 커밋은 둘 이상의 부모 ( "문어 병합")를 가질 수 있습니다. (이론적으로) 문어 병합을 일련의 두 부모 병합으로 대체 할 수는 있지만, Mercurial과 Git 리포지토리간에 변환 할 때 문제가 발생할 수 있습니다.
내가 아는 한 Mercurial에는 Git 의 주석 이 달린 태그 (태그 객체) 가 없습니다 . 주석이 달린 태그의 특수한 경우는 서명 된 태그입니다 (PGP / GPG 서명 포함). Mercurial과 동등한 것은 GpgExtension을 사용하여 수행 할 수 있으며 확장은 Mercurial과 함께 배포됩니다. Git에서와 같이 Mercurial에서 커밋 되지 않은 객체 에 태그를 지정할 수는 없지만 그다지 중요하지는 않습니다 (일부 git 리포지토리는 태그가있는 blob을 사용하여 서명 된 태그를 확인하는 데 공개 PGP 키를 배포합니다).
참조 : 브랜치 및 태그
Git 참조 (브랜치, 원격 추적 브랜치 및 태그)는 커밋의 DAG 외부에 상주합니다. refs/heads/
네임 스페이스 ( 로컬 브랜치 )의 참조는 커밋을 가리키며 일반적으로 "git commit"에 의해 업데이트됩니다. 그들은 가지의 끝 (머리)을 가리 키므로 그러한 이름입니다. refs/remotes/<remotename>/
네임 스페이스 ( 원격 추적 분기 )의 참조는 커밋을 가리키고 원격 저장소의 분기를 따르며 <remotename>
"git fetch"또는 이와 동등한 것으로 업데이트됩니다. refs/tags/
네임 스페이스 ( tags )의 참조는 일반적으로 커밋 (경량 태그) 또는 태그 객체 (주석 및 서명 된 태그 )를 가리키며 변경하려는 것은 아닙니다.
태그
Mercurial에서는 tag를 사용하여 수정 이름을 영구적으로 지정할 수 있습니다 . 태그는 무시 패턴과 유사하게 저장됩니다. 전역 적으로 볼 수있는 태그는 .hgtags
리포지토리의 개정 제어 파일에 저장됩니다. 그 결과 두 가지 결과가 발생합니다. 첫째, Mercurial은이 파일에 대한 모든 규칙을 사용하여 모든 태그의 현재 목록을 가져 와서 해당 파일을 업데이트해야합니다. 둘째, 다른 사용자 / 다른 저장소에 새 태그가 표시되도록이 파일에 변경 사항을 커밋해야합니다 (내가 이해하는 한).
Mercurial은 에 저장된 로컬 태그를 지원하며 다른 태그hg/localtags
는 볼 수 없으며 물론 양도 할 수 없습니다.
Git에서 태그는 refs/tags/
네임 스페이스에 저장된 다른 객체 (보통 커밋을 가리키는 태그 객체)에 대한 고정 된 (일정한) 명명 된 참조 입니다. 기본적으로 리비전 세트를 가져 오거나 푸시 할 때 git은 페치 또는 푸시되는 리비전을 가리키는 태그를 자동으로 가져 오거나 푸시합니다. 그럼에도 불구하고 어떤 태그를 가져 오거나 푸시 할지 어느 정도 제어 할 수 있습니다 .
Git은 경량 태그 (커밋을 직접 가리킴)와 주석이 달린 태그 (PGP 서명을 선택적으로 포함하는 태그 메시지를 포함하는 태그 메시지를 포함하는 태그 객체를 가리킴)를 약간 다르게 처리합니다. 예를 들어 기본적으로 설명 할 때 주석이 달린 태그 만 고려합니다 "git describe"를 사용하여 커밋합니다.
Git은 Mercurial에 엄격한 로컬 태그가 없습니다. 그럼에도 불구하고 자식 모범 사례는 준비된 변경 사항을 푸시하고 다른 사람이 복제하고 가져 오는 별도의 공개 베어 저장소를 설정하는 것이 좋습니다. 이것은 사용자가 푸시하지 않은 태그 (및 브랜치)가 리포지토리에 대해 비공개임을 의미합니다. 반면에 당신은 또한 이상의 네임 스페이스를 사용할 수 있습니다 heads
, remotes
또는 tags
예를 들어, local-tags
지역 태그.
개인적인 의견 : 제 의견으로는 태그는 외부에있는 수정 그래프 외부에 있어야합니다 (수정 그래프에 대한 포인터입니다). 태그는 버전이 아닌, 양도 할 수 있어야합니다. Mercurial은 파일을 무시할 때와 유사한 메커니즘을 사용하기로 선택했습니다. 즉, .hgtags
트리에서 특수하게 처리하거나 (파일 내에서 파일을 전송할 수 있지만 보통 버전을 지정 함) 로컬에만있는 태그 ( .hg/localtags
버전이 지정되지 않은, 그러나 양도 할 수 없음).
지점
Git 로컬 브랜치 (브랜치 팁 또는 브랜치 헤드)는 커밋에 대한 명명 된 참조로, 새로운 커밋을 증가시킬 수 있습니다. 지점은 또한 적극적인 개발 라인, 즉 지점 끝에서 도달 할 수있는 모든 커밋을 의미 할 수 있습니다. 로컬 브랜치는 refs/heads/
네임 스페이스에 상주 하므로 예를 들어 '마스터'브랜치의 정규화 된 이름은 'refs / heads / master'입니다.
Git의 현재 분기 (체크 아웃 된 분기 및 새로운 커밋이 진행되는 분기를 의미)는 HEAD ref가 참조하는 분기입니다. HEAD가 기호 참조가 아닌 커밋을 직접 가리 키도록 할 수 있습니다. 익명의 이름없는 브랜치에있는 이러한 상황을 분리 된 HEAD 라고합니다 ( "git branch"는 사용자가 '(브랜치 없음)'에 있음을 나타냅니다).
Mercurial에는 익명 브랜치 (브랜치 헤드)가 있으며 책갈피 확장을 통해 책갈피를 사용할 수 있습니다 . 이러한 책갈피 분기 는 순전히 로컬이며 해당 이름은 Mercurial을 사용하여 이전 할 수 없었습니다 (버전 1.6까지). rsync 또는 scp를 사용하여 .hg/bookmarks
파일을 원격 저장소 에 복사 할 수 있습니다 . hg id -r <bookmark> <url>
책갈피의 현재 팁의 개정 ID를 얻는 데 사용할 수도 있습니다 .
1.6 북마크 이후로 밀거나 끌 수 있습니다. BookmarksExtension의 페이지에 섹션이 원격 저장소 작업을 . Mercurial 북마크 이름이 전역 이라는 점에서 차이가 있지만 Git에서 '원격'의 정의는 원격 저장소의 이름에서 로컬 원격 추적 분기의 이름 으로 분기 이름의 맵핑 도 설명 합니다. 예를 들어 refs/heads/*:refs/remotes/origin/*
매핑은 'origin / master'원격 추적 분기 ( 'refs / remotes / origin / master')의 원격 저장소에서 'master'분기 ( 'refs / heads / master')의 상태를 찾을 수 있음을 의미합니다.
의욕은 또한 소위있다 라는 이름의 지점 지점 이름이되고, 내장 A는 (변경 집합에) 커밋합니다. 이러한 이름은 전역입니다 (가져 오기시 전송 됨). 이러한 분기 이름은 changeset \ u2019s 메타 데이터의 일부로 영구적으로 기록됩니다. 최신 Mercurial을 사용하면 "명명 된 지점"을 닫고 지점 이름 기록을 중지 할 수 있습니다. 이 메커니즘에서 분기의 팁은 즉시 계산됩니다.
머큐리얼의 "명명 된 브랜치"는 제 생각에 커밋 레이블 이라고 합니다. "명명 된 브랜치"에 여러 가지 팁 (여러 개의 자식이없는 커밋)이있을 수 있으며 여러 가지 불연속적인 수정 그래프로 구성 될 수도 있습니다.
Git에는 Mercurial "임베디드 브랜치"와 동등한 것이 없습니다. 게다가 Git의 철학은 브랜치에 커밋이 포함되어 있다고 말할 수 있지만 커밋이 일부 브랜치에 속한다는 것을 의미하지는 않습니다.
의욕 문서는 여전히 일명, 수명이 긴 지점에 대한 최소한 별도의 클론 (별도의 저장소) (저장소 워크 플로우 당 단일 지점)를 사용하도록 제안합니다 복제에 의해 분기 .
추진 지점
Mercurial은 기본적으로 모든 헤드를 푸시 합니다 . 단일 분기 ( 단일 헤드 )를 푸시하려면 푸시하려는 분기의 팁 개정을 지정해야합니다. 수정본 번호 (로컬에서 리포지토리로), 북마크 식별자 (로컬에서 리포지토리로, 전송되지 않음) 또는 내장 된 브랜치 이름 (지점으로)으로 분기 팁을 지정할 수 있습니다.
내가 이해하는 한, 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
구성 변수 를 통해 푸시 할 분기를 구성하지 않았다고 가정 합니다.
가져 오는 지점
참고 : 여기서 "fetch"는 변경 사항을 로컬 작업과 통합 하지 않고 원격 저장소에서 변경 사항을 다운로드하는 것을 의미하는 Git 용어를 사용 합니다. 이것이 " git fetch
"와 " hg pull
"의 역할입니다.
올바르게 이해하면 Mercurial은 기본적으로 원격 저장소에서 모든 헤드 를 가져 오지만 " hg pull --rev <rev> <url>
"또는 " hg pull <url>#<rev>
"를 통해 가져올 분기를 지정 하여 단일 분기 를 가져올 수 있습니다. 개정 식별자, "명명 된 브랜치"이름 (변경 로그에 포함 된 브랜치) 또는 책갈피 이름을 사용하여 <rev>를 지정할 수 있습니다. 그러나 북마크 이름은 (적어도 현재) 전송되지 않습니다. 소속 된 모든 "명명 된 브랜치"개정판이 이전됩니다. "hg pull"은 익명의 익명 헤드로 가져온 브랜치의 팁을 저장합니다.
기본적으로 Git ( "git clone"에 의해 생성 된 '원점'원격 및 "git remote add"에 의해 생성 된 원격)의 경우 " git fetch
"(또는 " git fetch <remote>
")는 원격 저장소 ( 네임 스페이스) 에서 모든 분기 를 가져 와서 refs/heads/
저장합니다. refs/remotes/
네임 스페이스. 예를 들어, 원격 'origin'에서 'master'(이름 : 'refs / heads / master') 라는 브랜치가 'origin / master' 원격 추적 브랜치 (전체 이름 : 'refs / 리모컨 / 원산지 / 마스터 ').
당신은 가져올 수 있습니다 단일 지점을 사용하여 힘내에서 git fetch <remote> <branch>
- 힘내 의욕 이름이 머리에 비슷한입니다 FETCH_HEAD에 요청 지점 (들)을 저장한다.
이것들은 강력한 refspec Git 구문 의 기본 사례의 예일뿐입니다. refspecs를 사용하면 가져올 브랜치 및 저장 위치를 지정 및 / 또는 구성 할 수 있습니다. 예를 들어 기본 "모든 분기 가져 오기"사례는 '+ refs / heads / * : refs / remotes / origin / *'와일드 카드 참조 스펙으로 표시되고 "단일 분기 가져 오기"는 'refs / heads / <branch> :'의 약어입니다. . Refspec은 원격 저장소의 분기 (refs) 이름을 로컬 참조 이름에 매핑하는 데 사용됩니다. 그러나 Git에서 효과적으로 작업 할 수 있도록 refspec에 대해 많은 것을 알 필요는 없습니다 (주로 "git remote"명령 덕분에).
개인적 의견 : 저는 개인적으로 Mercurial의 "명명 된 브랜치"(변경점 메타 데이터에 포함 된 브랜치 이름을 가진)가 특히 분산 버전 제어 시스템 의 경우 글로벌 네임 스페이스를 사용하여 잘못 설계되었다고 생각합니다 . 예를 들어 Alice와 Bob이 모두 저장소에 공통 이름이없는 "for-joe"라는 이름의 "named branch"가있는 경우를 예로 들어 보겠습니다. 그러나 Joe의 저장소에서이 두 분기는 단일 분기로 잘못 취급됩니다. 그래서 어떻게 든 브랜치 이름 충돌로부터 보호하는 규칙을 마련했습니다. 이것은 Joe의 저장소 'for-joe'분기에서 Alice의 'alice / for-joe'가되고 Bob의 경우 'bob / for-joe'가되는 Git에는 문제가되지 않습니다.
Mercurial의 "북마크 지점"에는 현재 핵심 배포 메커니즘이 없습니다.
차이점 : James woodyatt 와 Steve Losh 가 대답 한
것처럼 Mercurial과 Git의 주요 차이점 중 하나입니다 . Mercurial은 기본적으로 익명의 경량 코드 라인을 사용하는데, 그 용어로 "헤드"라고합니다. Git은 가벼운 이름의 브랜치를 사용하고, 원격 저장소의 브랜치 이름을 원격 추적 브랜치의 이름에 매핑하기 위해 인젝 티브 매핑을 사용합니다. Git은 분기 이름을 지정하도록 강제합니다 (단 하나의 명명되지 않은 분기, 분리 된 HEAD라고하는 상황 제외). 이것은 단일 저장소 패러다임의 여러 분기를 의미하는 주제 분기 워크 플로우와 같은 분기가 많은 워크 플로우에서 더 효과적이라고 생각합니다.
이름 수정
Git에는 여러 가지 방법으로 이름을 바꾸는 방법이 있습니다 (예 : git rev-parse 맨 페이지에 설명되어 있음).
- 전체 SHA1 오브젝트 이름 (40 바이트 16 진 문자열) 또는 저장소 내에서 고유 한 서브 스트링
- '마스터'( '마스터'분기 참조) 또는 'v1.5.0'(태그 참조) 또는 '원점 / 다음'(원격 추적 분기 참조)과 같은 상징적 참조 이름
^
수정 접미사 매개 변수는 커밋 개체의 첫 번째 부모를^n
의미하고 병합 커밋의 n 번째 부모를 의미합니다.~n
수정 접미사 매개 변수는 첫 번째 부모 선에서 커밋의 n 번째 조상을 의미합니다. 이러한 접미사를 결합하여 기호 참조에서 경로를 따라 수정 자 지정자를 형성 할 수 있습니다 (예 : 'pu ~ 3 ^ 2 ~ 3'- "git describe"의 결과, 즉 가장 가까운 태그, 선택적으로 대시 및 다수의 커밋, 대시, 'g'및 축약 된 오브젝트 이름 (예 : 'v1.6.5.1-75- g5bf8097 '.
여기에 언급되지 않은 reflog와 관련된 개정 지정자도 있습니다. Git에서 각 객체는 commit, tag, tree 또는 blob에 SHA-1 식별자가 있습니다. 지정된 개정판에서 트리 (디렉토리) 또는 BLOB (파일 내용)을 참조하는 'next : Documentation'또는 'next : README'와 같은 특수 구문이 있습니다.
Mercurial은 또한 변경 세트의 이름을 지정하는 많은 방법을 가지고 있습니다 (예 : hg 맨 페이지 에서 설명 )
- 일반 정수는 개정 번호로 취급됩니다. 개정 번호는 지정된 저장소에 대해 로컬 임을 기억해야 합니다 . 다른 저장소에서는 다를 수 있습니다.
- 음의 정수는 팁을 순차적으로 오프셋으로 처리하며 -1은 팁을, -2는 팁 이전의 개정을 나타냅니다. 또한 리포지토리에 로컬 입니다.
- 고유 한 개정 식별자 (40 자리 16 진 문자열) 또는 고유 한 접 두부.
- 태그 이름 (지정된 개정과 연관된 기호 이름) 또는 책갈피 이름 (확장자 : 지정된 헤드와 연관된 기호 이름, 저장소에 로컬) 또는 "명명 된 분기"(커밋 레이블; "명명 된 분기"에 의해 제공된 개정판은 주어진 커밋 레이블이있는 모든 커밋의 팁 (자식없는 커밋) (팁이 둘 이상인 경우 개정 번호가 가장 큼)
- 예약 된 이름 "tip"은 항상 최신 개정을 식별하는 특수 태그입니다.
- 예약 된 이름 "널"은 널 개정을 나타냅니다.
- 예약 된 이름 "." 작업 디렉토리 상위를 나타냅니다.
차이점
위의 목록을 비교할 수 있듯이 Mercurial은 저장소에 로컬 인 개정 번호를 제공하지만 Git은 그렇지 않습니다. 반면 Mercurial은 리포지토리에 로컬 인 'tip'(현재 브랜치)에서만 상대적 오프셋을 제공하며 (최소한 ParentrevspecExtension 없이 ) Git은 모든 팁에서 커밋을 지정할 수 있습니다.
가장 최근의 개정판은 Git에서 HEAD로, Mercurial에서 "tip"으로 명명되었습니다. Git에는 null 개정이 없습니다. Mercurial과 Git은 모두 루트가 많을 수 있습니다 (부모없는 커밋이 둘 이상있을 수 있음).
Elijah 's Blog (newren 's)에있는 여러 종류의 개정 지정자 기사 도 참조하십시오 .
개인적 견해 : 나는 개정 번호 가 과대 평가 된 것으로 생각합니다 (적어도 분산 개발 및 / 또는 비선형 / 지사 기록에 대해서는). 먼저, 분산 버전 제어 시스템의 경우 저장소에 대해 로컬이거나 로컬 번호 지정 기관으로 특별한 방식으로 일부 저장소를 처리해야합니다. 둘째, 더 긴 기록을 가진 더 큰 프로젝트는 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.
Mercurial 개정 범위는 개정 번호 범위를 기준으로 합니다 . 범위는 A:B
구문을 사용하여 지정 되며 Git 범위와 반대로 닫힌 간격으로 작동 합니다 . 또한 범위 B : A는 역순으로 범위 A : B이며, Git의 경우에는 해당되지 않습니다 (하지만 A...B
구문 에 대한 아래 참고 사항 참조 ). 그러나 이러한 단순성에는 가격이 따른다. 수정 범위 A : B는 A가 B의 조상이거나 그 반대의 경우, 즉 선형 이력이있는 경우에만 의미가있다. 그렇지 않으면 범위가 예측할 수 없으며 결과는 리포지토리에 로컬입니다 (개정 번호는 리포지토리에 로컬이기 때문에).
이것은 새로운 토폴로지 개정 범위 를 갖는 Mercurial 1.6으로 수정되었습니다 . 여기서 'A..B'(또는 'A :: B')는 X의 자손과 Y의 조상 인 변경 세트로 이해됩니다. Git의 '--ancestry-path A..B'와 같습니다.
Git A...B
은 개정의 대칭 적 차이에 대한 표기법도 가지고 있습니다 . 즉 A B --not $(git merge-base A B)
, A 또는 B에서 도달 할 수있는 모든 커밋을 의미하지만 둘 다에서 도달 할 수있는 모든 커밋은 제외합니다 (공통 조상에서 도달 할 수 있음).
이름 바꾸기
Mercurial은 이름 바꾸기 추적 을 사용 하여 파일 이름 바꾸기를 처리합니다. 이는 파일 이름이 변경되었다는 사실에 대한 정보가 커밋 시간에 저장됨을 의미합니다. Mercurial에서이 정보는 "향상된 diff"형식으로 filelog (파일 revlog) 메타 데이터에 저장됩니다. 결과적으로 hg rename
/ hg mv
... 를 사용해야 하거나 hg addremove
유사성 기반의 이름 바꾸기 감지 를 수행 하기 위해 실행해야합니다 .
Git은 파일 이름 변경을 처리 하기 위해 이름 변경 감지 를 사용한다는 점에서 버전 제어 시스템에서 고유 합니다. 이것은 파일 이름이 변경되었다는 사실이 필요할 때, 즉 병합을 수행 할 때 또는 diff를 표시 할 때 (요청 / 구성된 경우) 감지된다는 것을 의미합니다. 이는 이름 변경 감지 알고리즘을 개선 할 수 있고 커밋시 정지되지 않는 이점이 있습니다.
Git과 Mercurial은 --follow
단일 파일의 히스토리를 표시 할 때 이름 바꾸기를 수행하기 위해 옵션을 사용해야 합니다. git blame
/에 파일의 행별 히스토리를 표시 할 때 이름 변경을 따를 수 있습니다 hg annotate
.
Git에서 git blame
명령은 코드 이동을 수행 할 수 있으며 코드 이동이 건전한 파일 이름 바꾸기의 일부가 아니더라도 한 파일에서 다른 파일로 코드를 이동 (또는 복사) 할 수도 있습니다. 내가 아는 한,이 기능은 Git만의 고유 한 기능입니다 (작성 당시 2009 년 10 월).
네트워크 프로토콜
Mercurial과 Git은 동일한 파일 시스템에서 리포지토리를 가져오고 푸시하는 기능을 지원합니다. 여기서 리포지토리 URL은 리포지토리에 대한 파일 시스템 경로입니다. 둘 다 번들 파일 에서 가져 오기를 지원 합니다 .
SSH 및 HTTP 프로토콜을 통한 페치 및 푸시 지원 SSH의 경우 대상 컴퓨터에 액세스 가능한 셸 계정과 설치 / 사용 가능한 hg 사본이 필요합니다. HTTP 액세스를 위해서는 hg-serve
Mercurial CGI 스크립트가 실행 중이어야하며 서버 시스템에 Mercurial을 설치해야합니다.
Git은 원격 저장소에 액세스하는 데 사용되는 두 가지 종류의 프로토콜을 지원합니다.
- SSH를 통한 액세스 및 사용자 정의 git : // 프로토콜을 통한 액세스를 포함하는 "스마트"프로토콜
git-daemon
은 서버에 git이 설치되어 있어야합니다. 이러한 프로토콜의 교환은 클라이언트와 서버가 공통으로 가지고있는 객체에 대해 협상 한 다음 팩 파일을 생성 및 전송하는 클라이언트로 구성됩니다. 최신 Git은 "스마트 한"HTTP 프로토콜을 지원합니다. - HTTP 및 FTP (페치 전용) 및 HTTPS (WebDAV를 통한 푸시)를 포함하는 "dumb"프로토콜 은 서버에 git을 설치하지 않아도되지만 저장소에는 생성 된 추가 정보
git update-server-info
(일반적으로 후크에서 실행)가 포함되어야합니다. ). 교환은 클라이언트가 커밋 체인을 걷고 필요에 따라 느슨한 오브젝트와 팩 파일을 다운로드하는 것으로 구성됩니다. 단점은 엄격하게 필요한 것 이상을 다운로드하는 것입니다 (예를 들어 단일 팩 파일이 하나만있는 경우 모퉁이의 경우 약간의 개정 만 가져와도 전체 다운로드됩니다). 완료하려면 많은 연결이 필요할 수 있습니다.
확장 : 스크립트 가능성과 확장 (플러그인)
Mercurial은 성능을 위해 C로 작성된 일부 핵심 코드와 함께 Python 으로 구현됩니다 . 추가 기능을 추가하는 방법으로 확장 (플러그인) 을 작성하기위한 API를 제공 합니다. "책갈피 분기"또는 서명 개정과 같은 일부 기능은 Mercurial과 함께 배포 된 확장에서 제공되며이를 켜야합니다.
Git은 C , Perl 및 쉘 스크립트 로 구현됩니다 . Git은 스크립트에 사용하기에 적합한 많은 저수준 명령 ( 배관 )을 제공합니다 . 새로운 기능을 도입하는 일반적인 방법은이 기능을 Perl 또는 쉘 스크립트로 작성하는 것입니다. 사용자 인터페이스가 안정되면 성능, 이식성 및 쉘 스크립트가 코너 케이스를 피하는 경우 C로 다시 작성하십시오 (이 절차를 내장이라고 함 ).
Git은 [리포지토리] 형식과 [네트워크] 프로토콜을 기반으로하고 있습니다. 언어 바인딩 대신 다른 언어로 Git을 (부분적으로 또는 전체적으로) 다시 구현 합니다 (일부는 부분적으로 다시 구현하고 git 명령을 부분적으로 래퍼로 묶습니다) : JGit (Java, EGit에서 사용하는 Java, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).
TL; DR
두 비디오를 틀면 그 시스템이 비슷하거나 다른 점을 느낄 수 있다고 생각합니다.
Git의 Linus Torvalds ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Mercurial의 Bryan O'Sullivan ( http://www.youtube.com/watch?v=JExtkqzEoHY )
둘 다 디자인은 매우 유사하지만 구현 방식은 매우 다릅니다.
나는 Mercurial을 사용합니다. Git을 이해하는 한 git과 다른 점은 파일 자체 대신 파일의 내용을 추적한다는 것입니다. Linus는 한 파일에서 다른 파일로 함수를 이동하면 Git은 이동 중에 해당 단일 함수의 히스토리를 알려줍니다.
또한 git은 HTTP보다 느리지 만 자체 네트워크 프로토콜과 서버가 있다고 말합니다.
Git은 Mercurial보다 SVN 씩 클라이언트로 더 잘 작동합니다. SVN 서버를 당기고 밀 수 있습니다. 이 기능은 아직 Mercurial에서 개발 중입니다
Mercurial과 Git은 모두 매우 유용한 웹 호스팅 솔루션 (BitBucket 및 GitHub)을 제공하지만 Google Code는 Mercurial 만 지원합니다. 그건 그렇고, 그들은 지원 할 대상을 결정하기 위해 Mercurial과 Git을 매우 상세하게 비교했습니다 ( http://code.google.com/p/support/wiki/DVCSAnalysis ). 좋은 정보가 많이 있습니다.
얼마 전 Mercurial의 브랜칭 모델에 대한 블로그 항목을 작성했으며 git의 브랜칭 모델과 비교했습니다. 아마 당신은 재미있을 것입니다 : http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/
나는 꽤 정기적으로 사용합니다. 주요 기능상의 차이점은 Git 및 Mercurial 이름이 리포지토리 내에서 분기되는 방식에 있습니다. Mercurial을 사용하면 브랜치 이름이 변경 세트와 함께 복제되어 가져옵니다. Mercurial의 새 브랜치에 변경 사항을 추가하고 다른 저장소로 푸시하면 브랜치 이름이 동시에 푸시됩니다. 따라서 지점 이름은 Mercurial에서 거의 전역 적이며 책갈피 확장을 사용하여 로컬 전용 경량 이름을 사용해야합니다 (원하는 경우 Mercurial은 기본적으로 익명 경량 코드 라인을 사용함). "헤드"라고합니다. Git에서 브랜치 이름과 원격 브랜치에 대한 인젝 티브 매핑은 로컬로 저장되며이를 명시 적으로 관리해야합니다.
다른 사람들이 여기서 알 수 있듯이, 사소한 차이가 많이 있습니다. 가지가있는 것은 큰 차별화 요소입니다.
한 번 봐 가지고 힘내 대 의욕을 : 휴식을 취하시기 바랍니다 그가 기록 패트릭 톰슨에 의해 블로그 게시물 :
망할 놈의 맥가이버입니다 , 의욕은 제임스 본드입니다
이 블로그 게시물은 2008 년 8 월 7 일부터 작성되었으며 SCM은 그 이후로 많이 향상되었습니다.
Mercurial은 거의 완전히 파이썬으로 작성되었습니다. Git의 핵심은 C로 작성되었으며 Mercurial보다 빠르며 sh, perl, tcl로 작성된 도구이며 표준 GNU 유틸리티를 사용합니다. 따라서 이러한 모든 유틸리티와 인터프리터를 포함하지 않는 시스템 (예 : Windows)으로 통역사를 가져와야합니다.
AFAIK svn 지원은 Windows에서 git에 대해 중단되었지만 두 가지 지원은 SVN과 함께 작동합니다 (아는 사람은 운이 좋지 않거나 절름발이입니다). git과 Mercurial간에 상호 운용 할 수있는 확장 기능도 있습니다.
Mercurial은 멋진 Visual Studio 통합 기능을 갖추고 있습니다. 마지막으로 확인했을 때 Git 플러그인 이 작동했지만 매우 느 렸습니다.
기본 명령 세트는 매우 유사합니다 (init, clone, add, status, commit, push, pull 등). 따라서 기본 워크 플로는 동일합니다. 또한 TortoiseSVN과 유사한 클라이언트가 있습니다.
Mercurial 용 확장 프로그램은 파이썬으로 작성 될 수 있으며 (놀랍지 않습니다!) git 용으로 모든 실행 파일 형식 (실행 가능 바이너리, 쉘 스크립트 등)으로 작성 될 수 있습니다. 일부 확장 프로그램은 다음과 같이 강력 git bisect
합니다.
적절한 Windows 지원이 필요한 경우 Mercurial을 선호 할 수 있습니다. TortoiseHg (Windows 탐색기 플러그인)는 다소 복잡한 도구에 대한 간단한 그래픽 인터페이스를 제공합니다. 여기서 상태로 Visual Studio 플러그인도 있습니다. 그러나 마지막으로 시도했을 때 SVN 인터페이스가 Windows에서 제대로 작동하지 않았습니다.
커맨드 라인 인터페이스가 마음에 들지 않으면 Git을 추천합니다. 기술적 이유가 아니라 전략적인 이유 때문입니다. 자식 채택률이 훨씬 높습니다. cvs / svn에서 Mercurial로 전환하는 유명한 오픈 소스 프로젝트 수와 Git으로 전환되는 프로젝트 수를 확인하십시오. Mercurial 호스팅과 비교하여 git 지원으로 찾을 수있는 코드 / 프로젝트 호스팅 공급자 수를 확인하십시오.
Mercurial이 더 쉽다는 것을 읽은 후 (모든 인터넷 커뮤니티가 의견을 얻은 후에도 여전히 믿습니다), Git 및 Mercurial과 작업을 시작했을 때 Git이 적응하기가 비교적 간단하다고 느꼈습니다 (시작했습니다) 명령 줄에서 작업 할 때 주로 git 명령의 이름이 적절하고 이름이 적기 때문에 Mercurial with TortoiseHg) . Mercurial은 고유 한 작업을 수행하는 각 명령마다 이름이 다르지만 Git 명령은 상황에 따라 다목적 일 수 있습니다 (예 :checkout
). Git은 당시보다 더 어려웠지만 이제는 그 차이가 거의 없습니다. YMMV .. TortoiseHg와 같은 훌륭한 GUI 클라이언트를 사용하면 Mercurial을 사용하는 것이 훨씬 쉬웠으며 약간 혼란스러운 명령을 기억할 필요가 없었습니다. 동일한 작업에 대한 모든 명령이 어떻게 다른지 자세히 설명하지는 않지만 여기에는 Mercurial의 자체 사이트 와 wikivs 의 두 가지 포괄적 인 목록이 있습니다.
╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║ 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에 비해 히스토리를 쉽게 변경할 수 있지만 싫어하는 기능입니다. 나는 Hg는 전자를 좋아하고 Git은 후자를 좋아한다
내가 Hg에서 놓친 것은 Git의 서브 모듈 기능입니다. Hg에는 하위 리포지토리가 있지만 정확히 Git 하위 모듈은 아닙니다.
두 가지 주변의 생태계도 선택에 영향을 줄 수 있습니다 .Git은 더 인기가 있어야하지만 (사소한) Git에는 GitHub가 있고 Mercurial에는 BitBucket이 있고 Mercurial에는 TortoiseHg 가 있습니다 .Git 에 대한 것과 동등한 것으로 보지 못했습니다.
각각의 장점과 단점이 있으며 둘 중 하나를 잃지 않을 것입니다.
Scott Chacon의 게시물 을 잠시 후 확인하십시오 .
git은 "더 복잡한"것으로 유명하지만 내 경험상 필요 이상으로 복잡하지는 않다고 생각합니다. IMO는 자식 모델이다 방법 (태그 0 개 이상의 부모 커밋에 커밋 (및 포인터를 포함)를 포함 나무 완료 ... 모양과 다른 나무를 포함) 이해하기 쉽게.
git이 수은보다 더 혼란스럽지 않은 것은 단지 내 경험이 아닙니다. 이 문제에 대해 Scott Chacon의이 블로그 게시물을 다시 읽는 것이 좋습니다 .
나는 현재 직장에서 1 년 이상 조금씩 Git을 사용했으며 그 전에는 이전 직장에서 1 년 이상 Mercurial을 사용했습니다. 사용자 관점에서 평가를 제공 할 것입니다.
첫째, 둘 다 분산 버전 제어 시스템입니다. 분산 버전 제어 시스템은 기존 버전 제어 시스템에서 사고 방식을 변경해야하지만 실제로 이해하면 여러 가지 방식으로 훨씬 효과적으로 작동합니다. 이런 이유로 나는 Git과 Mercurial이 Subversion, Perforce 등보다 훨씬 우수하다고 생각합니다. 분산 버전 제어 시스템과 기존 버전 제어 시스템의 차이는 Git와 Mercurial의 차이보다 훨씬 큽니다.
그러나 Git과 Mercurial 간에는 각각의 사용 사례 하위 집합에 더 적합하도록하는 중요한 차이점이 있습니다.
머큐리얼은 배우기가 더 간단합니다. 나는 Mercurial을 사용한 지 몇 주 후에 문서 나 메모를 거의 언급하지 않는 시점에 도달했다. 1 년 동안 사용한 후에도 여전히 Git에서 정기적으로 노트를 참조해야합니다. 힘내는 훨씬 더 복잡합니다.
이것은 부분적으로 Mercurial이 단순한 클리너이기 때문입니다. 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은 Linux Kernel의 사실상 저장소이며 이것이 C 개발자들에게 인기가있는 이유 일 수 있습니다. 이것은 Linux / Unix 세계에서만 일하는 사치가있는 사람들에게 특히 그렇습니다.
Java 개발자는 Git보다 Mercurial을 선호하는 것 같습니다. 두 가지 이유가있을 수 있습니다. 하나는 JDK 자체를 포함하여 수많은 대규모 Java 프로젝트가 Mercurial에서 호스팅되기 때문입니다. 다른 하나는 Mercurial의 구조와 깔끔한 문서화가 Java 캠프에서 온 사람들에게 호소하는 반면, 그러한 사람들은 Git이 일관성없는 wrt 명령 이름 지정과 문서화 부족을 발견한다는 것입니다. 나는 그것이 사실이라고 말하는 것이 아닙니다. 사람들이 평소의 서식지에서 무언가에 익숙해 졌다고 말한 후 DVCS를 선택하는 경향이 있습니다.
파이썬 개발자는 거의 독점적으로 Mercurial을 선호합니다. Mercurial이 Python을 기반으로한다는 사실 이외의 합리적인 이유는 없습니다. (나는 Mercurial도 사용하고 사람들이 DVCS의 구현 언어에 대해 소란을 일으키는 이유를 정말로 이해하지 못한다. 나는 파이썬의 단어를 이해하지 못하고 그것이 어딘가에 나열되어 있다는 사실에 대해 이해하지 못한다면 파이썬을 기반으로하지만 알지 못했을 것입니다).
한 DVCS가 다른 DVCS보다 언어에 더 잘 맞는다고 말할 수는 없으므로 그 중에서 선택해서는 안됩니다. 그러나 실제로 사람들은 커뮤니티의 일부로 가장 많이 노출되는 DVCS를 기반으로 (부분적으로)를 선택합니다.
(아니요, 위의 소유권 주장을 뒷받침 할 사용 통계가 없습니다. 모두 본인의 주관성을 기반으로합니다)
참고 URL : https://stackoverflow.com/questions/1598759/git-and-mercurial-compare-and-contrast
'development' 카테고리의 다른 글
Android에서 URL로 ImageView를로드하는 방법은 무엇입니까? (0) | 2020.02.11 |
---|---|
안드로이드 : 이름을 사용하여 리소스에서 문자열을 얻는 방법은 무엇입니까? (0) | 2020.02.11 |
생성자 서명을 정의하는 인터페이스? (0) | 2020.02.11 |
__pycache__는 무엇입니까? (0) | 2020.02.10 |
JavaScript에서 부동 소수점 숫자 정밀도를 처리하는 방법은 무엇입니까? (0) | 2020.02.10 |