지트 부: 다중 환매와 선형 역사 합병
9962 단어 reinventingthewheelmadnessgit
$ git add .
$ git commit -m 'All together now!'
완성!아니오, 정말이 아니에요.이것은 역사를 없앨 것이다.나는 정말 그것을 보존하고 싶다.나는 자주 돌아가서 파일에 대해 어떤 변경을 했는지 확인하고, 어떤 코드가 언제 수정되었는지, 왜 수정되었는지 '책망' 을 사용한다.나는 어떻게 빨리 완성하는지 주위를 둘러보고 싶었다.나는 비슷한 사업을 묘사하는 블로그 게시물 한 무더기를 발견했다.코드 세션, 셸, 파이톤 스크립트, 심지어 자바 프로그램까지 찾아냈다.
그 중 일부를 시도한 후에 (자바가 아니야, 아니야, 고마워) 나는 그것들이 내가 원하는 것이 아니라는 것을 깨달았다.일부 작가들은 최초의 제출 해시를 보류하려고 시도했다.일부 작가들은 원본 파일 경로를 원한다.나는 역사가 시작되었을 때의 변화를 추적할 수 있기를 바란다.
내가 발견한 대다수의 방법은 모두 나의 목표에 부합되지 않는다.보통, 사람들은 하나의 리포를 하나의 지점으로 가져오려고 시도한다. (보통 다른 리포에서 하나를 추가하는 것
remote
에서 모든 파일을 제출할 때 하위 폴더로 이동한 다음, 이 지점을 master
에 통합시킨다.이것은 큰 제출을 만들고 모든 파일을 하위 폴더로 이동합니다.그 다음에 하나의 커다란 합병 제출이 있는데, 그 중 한 지점에서 온 모든 변경 사항이 다른 지점으로 복사되었다.GitHub에서 이러한 환매 협의를 보았을 때, 문서의 역사가 파괴되었음에도 불구하고 blame
.내장 명령
git subtree
도 발견했는데 그 결과 내가 이전에 시도한 모든 제3자 도구와 같은 문제가 있음을 발견했다.그러니까 가지 마!여기서 바퀴를 다시 설계하고 나만의 해결 방안을 제시해야 한다.그래서 기본적으로 나는 어떠한 합병 제출도 하지 않은 상황에서 모든 환매 협의를 합병하는 방법을 찾아야 한다.원본 파일을 하위 폴더로 이동해야 합니다.나는 두 개의 Git 도구를 생각했다.
cherry-pick
와 filter-branch
.방주몇 년 전에 나는 업무 중에 메르쿠릴을 사용한 적이 있다. 그것은 매우 좋다.Mercurial의 사용자 체험은 사람을 놀라게 한다.나는 그것이 서서히 죽지 않고 저질 제품이 개발 현장을 인수할 수 있기를 바란다.Mercurial은 직관적이고 사용자가 우호적인 것처럼 Git는 기능이 강하고 용도가 광범위하다.Git는 마치 삐뚤어진 레고 블록과 같다. 너는 그것으로 네가 원하는 모든 것을 만들 수 있다.
계획은 다음과 같습니다.
master
우선, 여느 때와 마찬가지로, 명령이 실패할 때, 스크립트 전체가 실패할 수 있도록 확보해야 한다.이것은 통상적으로 문제가 발생할 때 많은 시간을 절약할 수 있다.보통 이렇습니다.
#!/bin/bash
set -euo pipefail
내가 가입하고 싶은 환매 협의 목록:repos="1password bitwarden dashlane lastpass opvault passwordbox roboform stickypassword truekey zoho-vault"
처음부터 다시 시작하십시오.rm -rf joined
git init joined
cd joined
지금 여기서 까다로운 문제가 하나 있다.for repo in $repos; do
git remote add $repo $REPO_DIR/repo
git fetch $repo
git checkout -b $repo $repo/master
echo -n "$repo: " > prefix
git filter-branch \
-f \
--tree-filter "mkdir -p .original/$repo && rsync -a --remove-source-files ./ .original/$repo/" \
--msg-filter "cat $(pwd)/prefix -" \
--env-filter 'GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
$repo
rm prefix
done
하나씩 하나씩 봅시다.우선, 나는 재구매를 자신의 지점에 도입할 것이다.lastpass
라는 환매 협의는 최종적으로 lastpass
라는 지점에서 중지되었다.지금까지 별다른 어려움은 없었다.git remote add $repo $REPO_DIR/repo
git fetch $repo
git checkout -b $repo $repo/master
다음 단계에서, 제출할 때마다 파일을 하위 폴더로 이동할 수 있도록 모든 리포의 기록을 다시 쓸 것입니다.예를 들어 리포lastpass
에서 온 모든 파일은 최종적으로 .original/lastpass/
폴더에 있을 것이다.역사상의 모든 제출은 루트 디렉터리가 아닌 모든 개발이 이 폴더에서 이루어진 것처럼 변경됩니다.git filter-branch \
-f \
--tree-filter "mkdir -p .original/$repo && rsync -a --remove-source-files ./ .original/$repo/" \
--msg-filter "cat $(pwd)/prefix -" \
--env-filter 'GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
$repo
filter-branch
명령은 다기능 야수다.환매 협의가 제공하는 모든 가능한 전환을 통해 환매 협의는 식별할 수 없는 변화가 발생할 수 있다.FUBAR을 사용할 수도 있습니다.사실 이것은 매우 간단하다.Git가 refs/original/refs/heads
분기에 백업을 생성한 이유입니다.백업이 이미 존재하는 경우 -f
스위치를 사용하여 백업을 강제로 덮어씁니다.--tree-filter
스위치를 사용할 때 제출할 때마다 임시 디렉터리에 서명하고 일반적인 파일 조작을 사용하면 제출을 다시 쓸 수 있습니다.따라서 제출할 때마다 디렉터리 .original/$repo
를 만들고 rsync
를 사용하여 모든 파일을 이동합니다.--mag-filter
스위치는 내가 제출한 메시지를 다시 쓸 수 있도록 허락한다.lastpass
리포의 모든 제출이 lastpass: original commit message
처럼 보이도록 리포의 이름을 메시지에 추가하고 싶습니다.제출할 때마다 스크립트는 stdin
에서 제출 메시지를 수신하고 stdout
의 모든 내용은 새로운 제출 메시지가 됩니다.이 예에서 나는 cat
연결prefix
과 stdin
-
를 사용한다.어떤 이유로 단순echo -n
이 왜 작동하지 않는지 이해할 수 없기 때문에 메시지 접두사를 파일에 저장해야 합니다.마지막
--env-filter
은 제출 날짜를 원래 날짜(Git 용어의 작성자 날짜)로 재설정해야 합니다.만약 내가 이렇게 하지 않는다면, Git는 시간 스탬프를 현재 시간으로 변경할 것이다.그러고 싶지 않아요.다음 단계는 모든 제출을
master
지점에 복사해서 역사를 복원하는 것입니다.현재master
지점은 없습니다.우리 하나 하자.Git는 어떤 이유로 모든 파일을 색인에 추가하는 분기를 만들었습니다.git rm
로 그들을 죽였다.git checkout --orphan master
git rm -rf .
제출을 복사하려면 먼저 그것들을 열거해야 합니다.이 작업은 log
명령을 통해 수행됩니다.git log --pretty='%H' --author-date-order --reverse $repos
이 명령은 내가 이전에 만든 모든 지점에서 제출한 해시 값을 보여 주는 목록을 생성합니다. 가장 먼저부터 가장 최근까지의 정렬을 보여 줍니다.이 단계의 출력은 다음과 같습니다.7d62b1272b4aa37f07eb91bbf46a33609d80155f
a8673683cb13a2040299dcb9c98a6f1fcb110dbd
f3876d3a4900e7f6012efeb0cc06db241b0540d6
7209ecf519475e59494504ca2a75e36ad9ea6ebe
현재 나는 목록이 있는데, 나는 교체해서 cherry-pick
각각 master
에 제출한다.for i in $(git log --pretty='%H' --author-date-order --reverse $repos); do
GIT_COMMITTER_DATE=$(git log -1 --pretty='%at' $i) \
git cherry-pick $i
done
GIT_COMMITTER_DATE
환경 변수는 제출 날짜를 원래 생성 시간으로 재설정하는 데 다시 사용되며, 다음 그림과 같이 log
명령을 사용하여 다시 가져옵니다.git log -1 --pretty='%at' <COMMIT-HASH>
이 절차 후에 저는 역사가 평탄한 환매 협의가 생겼는데 그 중에서 모든 원시 환매 협의는 .original/
아래 자신의 하위 목록에 있습니다.나는 GitHub 파일의 기록과 탓을 사용하여 원본 파일이 태어난 이래 발생한 모든 변경 사항을 볼 수 있다.Git 곡의 이름이 바뀌었기 때문에, 나는 이 서류들을 megarepo 내의 새 집으로 옮길 수 있고, 나는 여전히 역사와 책임을 발휘할 수 있다.남은 유일한 일은 환매 협의를 정리하고 내가 더 이상 필요로 하지 않는 모든 지점을 삭제하며 쓰레기 수집기를 운행하여 쓰레기를 제거하는 것이다.
for repo in $repos; do
git branch -D $repo
git remote remove $repo
git update-ref -d refs/original/refs/heads/$repo
done
git gc --aggressive
이로 인해 발생하는 환매 기한here.나는 내가 투입한 시간이 가치가 있다고 생각한다.이것은 나로 하여금 Git 저급 명령에 대한 더 많은 정보를 얻을 수 있게 했다.현재 나는 환매 협의가 있어서, 나는 쉽게 훑어볼 수 있으며, 내가 일부 문서의 역사를 보고 싶을 때마다 지점 사이를 돌아다닐 필요가 없다.내가 사용한 스크립트를 찾을 수 있다here.
Reference
이 문제에 관하여(지트 부: 다중 환매와 선형 역사 합병), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/detunized/git-fu-merge-multiple-repos-with-linear-history-4kci텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)