소스 제어의 바이너리


30

임베디드 장치 및 기타 이상한 세계를 위해 개발할 때는 빌드 프로세스에 매우 특정한 버전의 독점 바이너리가 여러 개 포함되어있을 가능성이 높습니다. 문제는 소스 제어의 일부입니까? 내 사무실은 "소스 제어에서 체크 아웃하면 코드를 컴파일하는 데 필요한 모든 것이 포함됩니다"라는 규칙을 따릅니다. 이로 인해 몇 가지 심각한 주장이 제기되었습니다.

내가 이것에 반대하는 주된 논점은 소스 제어 DB를 부 풀리는 것입니다. 바이너리 파일을 나누는 것이 부족합니다 ( 주제에 대한 사전 질문 참조) . 이것은 이전 개발자가 의도 한 정확한 환경을 가지고 있고 적절한 파일을 찾지 않고 (특정 버전 이상으로) 알고 있는지 확인하고 빌드하는 능력에 위배됩니다.


3
또는 bash / python / perl / bat 스크립트를 작성하여 소스를 체크 아웃하고 한 번에 다른 모든 종속 구성 요소를 다운로드 할 수 있습니다. 그러나 개정판을 유지하기 위해 바이너리를 버전 관리에 체크인하는 것이 좋습니다. 리포지토리에 체크인하지 않아야하는 유일한 파일은 버전 제어 파일에서 쉽게 재생성 할 수있는 파일입니다. 디스크 공간이 저렴하므로 크게 고려해서는 안됩니다.
Lie Ryan

답변:


28

VERSION CONTROL (misnomer : source control)의 개념은 히스토리를 롤백하고 변경 효과를 복구하며 변경 사항 및 이유를 확인할 수 있도록하는 것입니다. 이것은 다양한 요구 사항이며, 일부는 이진 항목이 필요하고 일부는 필요하지 않습니다.

예 : 임베디드 펌웨어 작업의 경우 일반적으로 많은 비용이 드는 독점 컴파일러 또는 일부 버전의 gcc와 같은 완전한 툴체인이 있습니다. 배송 실행 파일을 얻으려면 소스뿐만 아니라 툴체인이 필요합니다.

툴 체인을 버전 제어로 확인하는 것은 고통스럽고 diff 유틸리티는 끔찍하지만 (아직도) 대안은 없습니다. 5 년 안에 코드를 살펴 보는 사람이 툴체인을 보존하기를 원한다면 그 선택을 할 수 없습니다. 툴체인도 버전 관리하에 있어야합니다.

수년 동안이 작업을 수행하는 가장 간단한 방법은 설치 CD의 ZIP 또는 ISO 이미지를 만들어 체크인하는 것입니다. 체크인 주석은 툴체인의 특정 제조업체 버전 번호 여야합니다. gcc 또는 이와 유사한 경우 사용중인 모든 것을 큰 ZIP으로 묶고 동일한 작업을 수행하십시오.

내가 한 가장 극단적 인 경우는 "툴체인"이 실행중인 Windows XP VM이며, 그 당시에는 SQL Server와 수백 개의 패치 파일과 함께 구성 파일 스택이 포함 된 Windows XP VM입니다. 전체 로트를 설치하고 최신 상태로 유지하는 데 2-3 일 정도 걸립니다. 후손을 유지한다는 것은 ENTIRE VM을 버전 제어로 확인하는 것을 의미했습니다. 가상 디스크가 약 6 x 2GB 이미지로 구성되어 있기 때문에 실제로는 꽤 잘 들어갔습니다. 소리가 잘 들리지만 5 년 후에 나를 따라 와서 사용해야하는 사람이 인생을 매우 쉽게 만들었습니다.

요약 : 버전 관리는 도구입니다. 그것을 효과적으로 사용하고, 단어의 의미와 같은 것들에 매달리지 말고, 그것보다 더 큰 "소스 컨트롤"이라고 부르지 마십시오.


1
VM을 리포 풍선을 12GB로 업데이트해야 할 때? 바이너리 diff가 좋은 경우에도 여전히 10GB 이상의 저장소를 사용하고 있습니다
TheLQ

3
음 ... 아니. VMWare를 사용하는 경우 디스크 스냅 샷을 사용할 수 있습니다. 이들은 원래 기준 디스크 이미지를 저장하고 델타 만 포함하는 새 파일을 추가합니다. 새로 만든 파일을 체크인해야합니다. 마지막으로 이것을 살펴보면 약 250K의 치킨 피드 업데이트가 추가되었습니다. 게다가, repo 크기에 대한 걱정은 무의미합니다-디스크는 저렴합니다.
quick_now

임베디드 툴 체인이 네트워크 라이센스에 의존하는 경우는 어떻습니까 :)
Dan

18

닐 포드의 주장 는 The Productive 프로그래머 는 것을 해야 소스 컨트롤에서 바이너리를 유지 :

바이너리를 유지하는 이유는 무엇입니까? 오늘날의 프로젝트는 다양한 외부 도구와 라이브러리에 의존합니다. Log4J 또는 Log4Net과 같이 널리 사용되는 로깅 프레임 워크 중 하나를 사용한다고 가정 해 봅시다. 빌드 프로세스의 일부로 해당 로깅 라이브러리의 바이너리를 빌드하지 않는 경우 버전 관리에 보관해야합니다. 이를 통해 문제의 프레임 워크 또는 라이브러리가 사라지더라도 소프트웨어를 계속 빌드 할 수 있습니다. 버전 관리에서 소프트웨어를 구축하는 데 필요한 전체 유니버스를 항상 유지(운영체제를 빼고 가상화에서도 가능합니다.이 장 뒷부분의 "가상화 사용"참조). 바이너리를 버전 관리 및 공유 네트워크 드라이브에 유지하여 유지 바이너리를 최적화 할 수 있습니다. 그렇게하면 시간 단위로 처리 할 필요는 없지만 1 년 후 무언가를 다시 만들어야하는 경우에 대비하여 저장됩니다. 무언가를 재건해야하는지 절대 알 수 없습니다. 작동 할 때까지 빌드 한 다음 잊어 버리십시오. 2 년 전부터 무언가를 재건해야하고 모든 부품을 가지고 있지 않다는 사실을 깨닫는 것은 당황 스럽습니다.

나는 더 이상 동의 할 수 없었다. 이것은 바이너리를 유지하기 위해 설계되지 않은 작업에 대해 VCS를 전복시킬 수 있지만 이점은 잠재적 인 단점보다 중요하다고 생각합니다. 그러나 작성자가 나중에 언급했듯이 때때로 바이너리를 VCS에 유지하는 것은 실용적인 해결책이 아닐 수 있으므로 매핑 된 네트워크 드라이브에 보관하는 것과 같은 다른 옵션을 고려해야합니다.

바이너리가 너무 크지 않으면 VCS에 보관할 것입니다. 이 바이너리 아마 작기 때문에, 더욱 사실 귀하의 경우 것 같다, 그리고 당신은 매우 특정 버전과 함께 작동합니다. 여러 가지 이유로 인해 찾기가 어려울 수도 있습니다 (저자가 웹 사이트를 종료하거나 필요한 버전이 더 이상 다운로드 용으로 나열되지 않음). 가능하지는 않지만 몇 년 안에 어떤 일이 일어날 지 전혀 알 수 없습니다.

그래픽 라이브러리 (dll 파일)를 사용하여 게임을 할 때 몇 년 전에이 책을 읽었 으면합니다. 개발을 잠시 중단했으며 계속하고 싶을 때 프로젝트가 종료되어 dll을 다시 찾을 수 없었습니다.


2
예, 이것은 너무 자주 발생합니다. 저는 3-4 년 전에 저자가 버린 스캐너 생성기에 의존하는 취미 프로젝트를 가지고 있습니다. 운 좋게도 항상 버전 관리하에있었습니다.
Christian Klauser

9

원칙적으로, 나는 "소스 제어에 구축하기 위해 필요한 모든 것을 점검하라"캠프에 감사하지만, 지난 몇 년 동안 Maven, Ivy 및 NuGet과 같은 도구를 사용하여 종속성 관리가 상당히 발전했다.

또한 실제로 바이너리를 체크인하여 여러 가지 불쾌한 부작용을 만듭니다. 예를 들어 Git / Mercurial은 실제로 조정되지 않았으며, Subversion과 Perforce는 바이너리가 포함 된 분기를 병합 할 때 견과류를 구동 할 수 있습니다.

종속성 관리 솔루션을 사용하면 프로젝트의 소스 이름 파일에서 패키지 이름과 프로젝트의 버전을 지정합니다. 거의 모든 종속성 관리 도구를 사용하면 일종의 버전 관리 및 명명 규칙에 따라 종속성의 개인 리포지토리를 만들 수 있습니다. 빌드를 수행 할 때 종속성 관리 도구는 승인 된 소스 목록에서 모든 공개 소스 및 독점 종속성을 해결 한 다음 로컬 캐시에 넣습니다. 다음에 동일한 버전 종속성으로 빌드하면 모든 것이 이미 존재하며 훨씬 빠릅니다.

개인 저장소는 기존 파일 시스템 백업 도구를 사용하여 백업 할 수 있습니다.

이렇게하면 소스 트리에서 많은 이진 파일을 가져올 때 발생하는 속도 저하를 피할 수 있으며 리포지토리에서 파일을 찾기 어려운 많은 파일을 가질 수 없습니다. 이름 및 버전 번호별로 특정 종속성에 대한 위치는 하나뿐이므로 처리 할 병합 충돌이 없으며 로컬 파일 시스템 캐싱은 로컬 사본이 변경되었을 때 로컬 사본이 변경되었는지 평가하는 비용을 처리 할 필요가 없음을 의미합니다. 업데이트를 가져옵니다.


8

소스 제어는 소스를위한 것입니다. 소스는 다른 것들로 만들 수없는 것입니다. 소스로 적합한 일부 파일은 이진 파일입니다.

내 VCS에는 많은 바이너리가 체크인되어 있지만 각각은 내가 작성하지 않았고 유지하지 않는 일부 제품의 릴리스 단위입니다. 이것은 압축 된 tarball로 릴리즈 된 GNU ccRTP와 같은 것일 수 있습니다. 그 tarball은 내 소스이며, 자동화 된 단일 단계에서 완성 된 제품 (제 경우에는 Makefile 및 RPM 사양)으로 변환해야하는 모든 인프라와 함께 체크인됩니다. ccRTP의 새 버전이 있으면 새 tarball을 변경된 소스로 취급합니다. 체크 아웃 된 사본으로 이동하여 빌드, 테스트 및 VCS에 다시 커밋합니다. 소스 (컴파일러, 라이브러리 등)와 함께 제공되지 않는 상용 제품에서 동일한 작업을 수행했으며 동일한 방식으로 작동합니다. unpack-configure-compile-package 대신에 단지 unpack-package입니다. 야간 빌드를 수행하는 소프트웨어는make 그리고 완제품을 얻으십시오.

대부분의 VCS에는 사람이 읽을 수있는 소스를 다루기 쉽고 저장하기에 더 효율적으로 만드는 기능이 있지만 바이너리에 적합하지 않다고 말하는 것이 바이너리를 몰래 다시 가져 오는 경우에는 실제로 사실이 아닙니다. VCS가 바이너리를 내부적으로 처리하는 방법은 전적으로 작성자가 차이점 만 저장하려고 시도하는 것이 노력할만한 가치가 있는지 여부에 달려 있습니다. 개인적으로, ccRTP 배포본의 전체 사본을 600K로 저장하면 팝 버전이 다른 모든 소스와 함께 버전을 태그하는 기능으로 구성되는 것 이상이라고 생각합니다.


4

이것은 얼마 전에 Java가 가지고 있었던 "저장소에있는 JAR"문제를 떠올리게합니다. Java 앱을 빌드하는 사람들은 종속성 (이진 jar 파일)을 저장소로 푸시하는 데 사용되었습니다. 우리는 당신이 "원 클릭"빌드 시스템을 가질 것이고 디스크 공간이 저렴하기 때문에 모두가 이것에 만족했습니다. 그런 다음 Maven이 왔으며 이진 크래프트를 모두 제거하고 로컬 캐시 전용 리포지토리를 사용하여 여전히 bullet-prof 빌드를 유지할 수 있습니다. 여전히 "원 클릭"빌드 시스템이 있지만 소스 제어는 이진 파일을 뒤섞을 필요가 없습니다.

예, 소스 컨트롤에서 바이너리 파일을 가져올 수 있지만 빌드시 시스템을 조정하여 빌드시 파일을 가져와야합니다. Maven과 같은 전용 소프트웨어가 없으면 소프트웨어를 꺼내기 위해 많은 노력을 기울일 수 있습니다.


1
팀의 많은 부분이 수학자이고 많은 프로세스 팬이 아니기 때문에 빌드 프로세스를 복잡하게 만드는 것에 대해 걱정하고 있습니다.
Daniel Goldberg

3

당신의 소스 컨트롤은 당신이하는 일에 소스 를 가지고 있습니다. 주어진 바이너리 BLOB을 소스에서 재구성 할 수있는 경우 소스가 아니므로 소스 코드 저장소에 들어가면 안됩니다. 소스 컨트롤에는 재생 불가능한 얼룩 만 있어야합니다.

일반적으로 소스 시간을 통해 빌드 한 이진 Blob의 다른 리포지토리 네트워크 폴더가 있습니다. 이들은 처음부터 모든 것을 처음부터 구축하는 대신 고객에게 배포하거나 프로젝트에 사용할 수 있습니다.

따라서 그것이 출처라면 넣습니다. 그렇지 않다면하지 마십시오.


누가 이것을 공감할 것인가? 흥미로운 이유 : D

그것은 내가 아니었지만, 나는 그것이 답의 후반부에 동의하지 않은 사람을 의심합니다.
Joel Coehoorn

흥미롭게도 @JoelCoehoorn은 Maven 저장소가 그대로입니다.

2

목표는 무엇이든 설치 / 설정하지 않고도 최신 코드를 가져 와서 빌드 할 수 있도록하는 것입니다 (따라서 "단일 클릭"빌드).

많은 곳에서 나는 바이너리 바이너리를 체크인하는 것을 의미합니다. 즉, 빌드 스크립트는 종속성을 자동으로 다운로드하여 가져옵니다.

주제에 관한 Derek Greer 의이 블로그 게시물 을 참조하십시오 .


2

두 가지 빌드 단계로 프로젝트를 진행 중입니다.

  • "주 프로그램 빌드"는 수천 개의 소스 코드 텍스트 파일에 비해 몇 개의 바이너리 만 필요하므로 바이너리는 저장소에 체크인됩니다. 이것은 잘 작동합니다.

  • 설치 프로그램 빌드에는 많은 타사 구성 요소가 필요합니다 (일부 구성 요소는 Adobe Reader와 같은 설치 CD로 복사 됨). 우리는 그것들을 저장소에 넣지 않습니다. 대신 이러한 구성 요소는 네트워크 드라이브 (이전 버전의 구성 요소)에 있으며 빌드 스크립트는 해당 구성 요소를 올바른 위치에 복사합니다. 물론 재현 가능한 빌드를 위해서는 타사 구성 요소가 저장된 폴더를 변경하지 않도록주의해야합니다.

두 전략 모두 제대로 작동하고 "코드를 컴파일하는 데 필요한 모든 것이 소스 제어에서 체크 아웃"요구 사항을 충족합니다.


1

나중에 특정 버전의 제품을 다시 빌드하는 데 필요한 모든 것을 유지해야합니다.

그러나 모든 것을 소스 제어에 유지할 필요는 없습니다.

한 회사가 정지 된 서버 랙을 유지했습니다 (OS는 특정 하드웨어에서만 실행되고 툴체인은 해당 OS에서만 실행되고 소스는 해당 툴체인에 의존하기 때문에). 소스 컨트롤로 확인할 수 없습니다.

빌드 요구 사항을 분할해야하는 경우 두 버전 제어 시스템을 동기화 상태로 유지해야하는 회계 문제가 있습니다. 예를 들어이 옷장의 하드웨어 상자 또는이 보존 된 백업 볼륨의 VM 또는 이진 파일은이 SVN 소스 코드 개정판과 함께 사용됩니다. 이는 단일 소스 제어 시스템을 사용하지만 해결할 수있는 것이 더 지저분합니다.


0

바이너리를 SCM에 체크인하는 것은 매우 혼돈입니다. 나는 매우 복잡한 프로젝트를 실행했는데, 이는 제 3의 파트 라이브러리에 많은 의존성을 가지고 있습니다. 우리가 채택한 원칙 :

  1. 모든 소스 코드는 SCM으로 관리
  2. 모든 의존성은 Ivy로 관리되며, 이클립스 통합이 뛰어납니다.

이것은 꽤 잘 작동합니다. 소스 코드를 컴파일 할 수있는 각 외부 라이브러리의 버전에 대한 구성 파일이 있습니다. 이 구성 파일은 SCM에 체크인되므로 소스 코드가 발전함에 따라 진화합니다. 이 접근법을 적용하면 외부 라이브러리 버전을 망칠 필요없이 빌드를 정확하게 재현 할 수 있습니다.


0

개인적으로, 철학적으로 소스 제어가 파일의 내용이 아닌 큰 이진 파일 (작은 이진 리소스는 괜찮음) 에 대한 포인터 를 체크인하도록하는 경향 이 있습니다. 이 포인터는 바이너리 파일 내용의 해시를 포함합니다.

이진 파일 자체는 소스 제어로 관리되지 않습니다. 포인터 또는 해시를 사용하여 검색 할 수있는 일종의 라이브러리에 저장됩니다.

Git LFS와 git annex는 그렇게하지만 바이너리 파일을 어느 정도 관리하려고 시도합니다. Git이 체크섬 만 저장하고 바이너리 파일이 변경되었는지 여부를 알려주기를 원하지만 관리하고 저장하려고하지 않습니다. 나는 이것을 직접하고 싶다.

git이 중소 규모의 이진 파일을 처리 할 수 ​​있다고 생각하지만 큰 이진 파일을 관리하는 데 적합한 도구인지 확실하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.