簡體   English   中英

如何將一些文件從一個 git 存儲庫移動到另一個(不是克隆),保留歷史記錄

[英]How to move some files from one git repo to another (not a clone), preserving history

我們的 Git 存儲庫最初是作為單個怪物 SVN 存儲庫的一部分,其中每個項目都有自己的樹,如下所示:

project1/branches
        /tags
        /trunk
project2/branches
        /tags
        /trunk

顯然,使用svn mv將文件從一個文件移動到另一個文件非常容易。 但是在 Git 中,每個項目都在自己的存儲庫中,今天我被要求將一個子目錄從project2移動到project1 我做了這樣的事情:

$ git clone project2 
$ cd project2
$ git filter-branch --subdirectory-filter deeply/buried/java/source/directory/A -- --all
$ git remote rm origin  # so I don't accidentally overwrite the repo ;-)
$ mkdir -p deeply/buried/different/java/source/directory/B
$ for f in *.java; do 
>  git mv $f deeply/buried/different/java/source/directory/B
>  done
$ git commit -m "moved files to new subdirectory"
$ cd ..
$
$ git clone project1
$ cd project1
$ git remote add p2 ../project2
$ git fetch p2
$ git branch p2 remotes/p2/master
$ git merge p2 # --allow-unrelated-histories for git 2.9+
$ git remote rm p2
$ git push

但這似乎很復雜。 一般來說,有沒有更好的方法來做這種事情? 還是我采用了正確的方法?

請注意,這涉及將歷史合並到現有存儲庫中,而不是簡單地從另一個存儲庫的一部分創建一個新的獨立存儲庫( 如前面的問題)。

如果您的歷史記錄是健全的,您可以將提交作為補丁取出並將它們應用到新存儲庫中:

cd repository
git log --pretty=email --patch-with-stat --reverse --full-index --binary -- path/to/file_or_folder > patch
cd ../another_repository
git am --committer-date-is-author-date < ../repository/patch 

或者在一行

git log --pretty=email --patch-with-stat --reverse --full-index --binary -- path/to/file_or_folder | (cd /path/to/new_repository && git am --committer-date-is-author-date)

(取自Exherbo 的文檔

嘗試了各種方法將文件或文件夾從一個 Git 存儲庫移動到另一個存儲庫后,下面概述了唯一一種似乎可靠工作的方法。

它涉及克隆要從中移動文件或文件夾的存儲庫,將該文件或文件夾移動到根目錄,重寫 Git 歷史記錄,克隆目標存儲庫並將具有歷史記錄的文件或文件夾直接拉入此目標存儲庫。

第一階段

  1. 制作存儲庫 A 的副本,因為以下步驟對此副本進行了重大更改,您不應該推送!

     git clone --branch <branch> --origin origin --progress \ -v <git repository A url> # eg. git clone --branch master --origin origin --progress \ # -v https://username@giturl/scm/projects/myprojects.git # (assuming myprojects is the repository you want to copy from)
  2. cd進去

    cd <git repository A directory> # eg. cd /c/Working/GIT/myprojects
  3. 刪除原始存儲庫的鏈接以避免意外進行任何遠程更改(例如通過推送)

     git remote rm origin
  4. 瀏覽您的歷史記錄和文件,刪除不在目錄 1 中的任何內容。結果是目錄 1 的內容涌入存儲庫 A 的基礎。

     git filter-branch --subdirectory-filter <directory> -- --all # eg. git filter-branch --subdirectory-filter subfolder1/subfolder2/FOLDER_TO_KEEP -- --all
  5. 僅用於單個文件移動:檢查剩下的內容並刪除除所需文件之外的所有內容。 (您可能需要刪除不想要的同名文件並提交。)

     git filter-branch -f --index-filter \ 'git ls-files -s | grep $'\t'FILE_TO_KEEP$ | GIT_INDEX_FILE=$GIT_INDEX_FILE.new \ git update-index --index-info && \ mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || echo "Nothing to do"' --prune-empty -- --all # eg. FILE_TO_KEEP = pom.xml to keep only the pom.xml file from FOLDER_TO_KEEP

第二階段

  1. 清理步驟

    git reset --hard
  2. 清理步驟

    git gc --aggressive
  3. 清理步驟

    git prune

您可能希望將這些文件導入到存儲庫 B 中的目錄而不是根目錄中:

  1. 制作那個目錄

    mkdir <base directory> eg. mkdir FOLDER_TO_KEEP
  2. 將文件移動到該目錄

    git mv * <base directory> eg. git mv * FOLDER_TO_KEEP
  3. 將文件添加到該目錄

    git add .
  4. 提交您的更改,我們已准備好將這些文件合並到新存儲庫中

    git commit

第三階段

  1. 如果您還沒有存儲庫 B,請復制存儲庫 B

     git clone <git repository B url> # eg. git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git

    (假設 FOLDER_TO_KEEP 是您要復制到的新存儲庫的名稱)

  2. cd進去

    cd <git repository B directory> # eg. cd /c/Working/GIT/FOLDER_TO_KEEP
  3. 創建到存儲庫 A 的遠程連接作為存儲庫 B 中的分支

    git remote add repo-A-branch <git repository A directory> # (repo-A-branch can be anything - it's just an arbitrary name) # eg. git remote add repo-A-branch /c/Working/GIT/myprojects
  4. 從此分支(僅包含您要移動的目錄)拉入存儲庫 B。

     git pull repo-A-branch master --allow-unrelated-histories

    拉取復制文件和歷史記錄。 注意:您可以使用合並而不是拉取,但拉取效果更好。

  5. 最后,您可能想通過刪除與存儲庫 A 的遠程連接來清理一下

    git remote rm repo-A-branch
  6. 推動,一切就緒。

     git push

是的,點擊filter-branch--subdirectory-filter是關鍵。 您使用它的事實基本上證明沒有更簡單的方法 - 您別無選擇,只能重寫歷史記錄,因為您希望最終只得到文件的(重命名)子集​​,而這根據定義會更改哈希值。 由於沒有任何標准命令(例如pull )重寫歷史記錄,因此您無法使用它們來完成此操作。

當然,您可以改進細節 - 您的一些克隆和分支並不是絕對必要的 - 但整體方法很好! 很遺憾它很復雜,但當然,git 的目的並不是讓重寫歷史變得容易。

我發現Ross Hendrickson 的博客非常有用。 這是一種非常簡單的方法,您可以在其中創建應用於新存儲庫的補丁。 有關更多詳細信息,請參閱鏈接頁面。

它只包含三個步驟(從博客復制):

# Setup a directory to hold the patches
mkdir <patch-directory>

# Create the patches
git format-patch -o <patch-directory> --root /path/to/copy

# Apply the patches in the new repo using a 3 way merge in case of conflicts
# (merges from the other repo are not turned into patches). 
# The 3way can be omitted.
git am --3way <patch-directory>/*.patch

我遇到的唯一問題是我無法一次應用所有補丁

git am --3way <patch-directory>/*.patch

在 Windows 下我得到一個 InvalidArgument 錯誤。 所以我不得不一個接一個地應用所有補丁。

這通過使用 git-filter-repo 變得更簡單。

為了將project2/sub/dir移動到project1/sub/dir

# Create a new repo containing only the subdirectory:
git clone project2 project2_clone --no-local
cd project2_clone
git filter-repo --path sub/dir

# Merge the new repo:
cd ../project1
git remote add tmp ../project2_clone/
git fetch tmp master
git merge remotes/tmp/master --allow-unrelated-histories
git remote remove tmp

要簡單地安裝該工具: pip3 install git-filter-repo更多詳細信息和選項在 README 中

# Before: (root)
.
|-- project1
|   `-- 3
`-- project2
    |-- 1
    `-- sub
        `-- dir
            `-- 2

# After: (project1)
.
├── 3
└── sub
    └── dir
        └── 2

保留目錄名稱

子目錄過濾器(或更短的命令 git subtree)效果很好,但對我不起作用,因為它們從提交信息中刪除了目錄名稱。 在我的場景中,我只想將一個存儲庫的一部分合並到另一個存儲庫中,並保留帶有完整路徑名的歷史記錄。

我的解決方案是使用樹過濾器並簡單地從源存儲庫的臨時克隆中刪除不需要的文件和目錄,然后通過 5 個簡單的步驟從該克隆中提取到我的目標存儲庫中。

# 1. clone the source
git clone ssh://<user>@<source-repo url>
cd <source-repo>
# 2. remove the stuff we want to exclude
git filter-branch --tree-filter "rm -rf <files to exclude>" --prune-empty HEAD
# 3. move to target repo and create a merge branch (for safety)
cd <path to target-repo>
git checkout -b <merge branch>
# 4. Add the source-repo as remote 
git remote add source-repo <path to source-repo>
# 5. fetch it
git pull source-repo master
# 6. check that you got it right (better safe than sorry, right?)
gitk

我經常使用的是http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/ 簡單快速。

為了符合 stackoverflow 標准,以下是過程:

mkdir /tmp/mergepatchs
cd ~/repo/org
export reposrc=myfile.c #or mydir
git format-patch -o /tmp/mergepatchs $(git log $reposrc|grep ^commit|tail -1|awk '{print $2}')^..HEAD $reposrc
cd ~/repo/dest
git am /tmp/mergepatchs/*.patch

有類似的癢癢(盡管僅適用於給定存儲庫的某些文件),這個腳本被證明非常有用: git-import

簡短的版本是它從現有存儲庫創建給定文件或目錄( $object )的補丁文件:

cd old_repo
git format-patch --thread -o "$temp" --root -- "$object"

然后將其應用於新的存儲庫:

cd new_repo
git am "$temp"/*.patch 

詳情請查閱:

更新(來自另一位作者) 這個有用的方法可以被以下bash 函數使用。 這是一個示例用法:

gitcp <Repo1_basedir> <path_inside_repo1> <Repo2_basedir>

gitcp ()
{
    fromdir="$1";
    frompath="$2";
    to="$3";
    echo "Moving git files from "$fromdir" at "$frompath" to "$to" ..";
    tmpdir=/tmp/gittmp;
    cd "$fromdir";
    git format-patch --thread -o $tmpdir --root -- "$frompath";
    cd "$to";
    git am $tmpdir/*.patch
}

這個答案提供了基於git am的有趣命令,並使用示例一步一步地呈現。

客觀的

  • 您希望將部分或全部文件從一個存儲庫移動到另一個存儲庫。
  • 你想保留他們的歷史。
  • 但是您並不關心保留標簽和分支。
  • 您接受重命名文件(以及重命名目錄中的文件)的有限歷史記錄。

程序

  1. 使用電子郵件格式提取歷史記錄
    git log --pretty=email -p --reverse --full-index --binary
  2. 重新組織文件樹並更新歷史記錄中的文件名更改 [可選]
  3. 使用git am應用新的歷史記錄

1.以電子郵件格式提取歷史記錄

示例:提取file3file4file5的歷史記錄

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

清理臨時目錄目標

export historydir=/tmp/mail/dir  # Absolute path
rm -rf "$historydir"             # Caution when cleaning

清理你的 repo

git commit ...           # Commit your working files
rm .gitignore            # Disable gitignore
git clean -n             # Simulate removal
git clean -f             # Remove untracked file
git checkout .gitignore  # Restore gitignore

以電子郵件格式提取每個文件的歷史記錄

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

不幸的是,選項--follow--find-copies-harder不能與--reverse結合使用。 這就是為什么當文件被重命名(或父目錄被重命名)時歷史被刪除的原因。

之后:電子郵件格式的臨時歷史記錄

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

2.重新組織文件樹並更新歷史中的文件名更改[可選]

假設您想將這三個文件移動到另一個 repo 中(可以是同一個 repo)。

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # was subdir
│   │   ├── file33    # was file3
│   │   └── file44    # was file4
│   └── dirB2         # new dir
│        └── file5    # = file5
└── dirH
    └── file77

因此重新組織您的文件:

cd /tmp/mail/dir
mkdir     dirB
mv subdir dirB/dirB1
mv dirB/dirB1/file3 dirB/dirB1/file33
mv dirB/dirB1/file4 dirB/dirB1/file44
mkdir    dirB/dirB2
mv file5 dirB/dirB2

您的臨時歷史現在是:

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

更改歷史記錄中的文件名:

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

注意:這會重寫歷史記錄以反映路徑和文件名的更改。
(即新倉庫中新位置/名稱的更改)


3.應用新的歷史

您的另一個回購是:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

從臨時歷史文件應用提交:

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am 

你的另一個倉庫現在是:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB            ^
│   ├── dirB1       | New files
│   │   ├── file33  | with
│   │   └── file44  | history
│   └── dirB2       | kept
│        └── file5  v
└── dirH
    └── file77

使用git status查看准備推送的提交數量 :-)

注意:由於歷史記錄已被重寫以反映路徑和文件名的更改:
(即與上一個 repo 中的位置/名稱相比)

  • 無需git mv即可更改位置/文件名。
  • 無需git log --follow即可訪問完整歷史記錄。

額外技巧:在你的倉庫中檢測重命名/移動的文件

要列出已重命名的文件:

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

更多自定義:您可以使用選項--find-copies-harder harder 或--reverse完成命令git log 您還可以使用cut -f3-和 grepping 完整模式 '{.* => .*}' 刪除前兩列。

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'

嘗試這個

cd repo1

這將刪除除提到的目錄之外的所有目錄,僅保留這些目錄的歷史記錄

git filter-branch --index-filter 'git rm --ignore-unmatch --cached -qr -- . && git reset -q $GIT_COMMIT -- dir1/ dir2/ dir3/ ' --prune-empty -- --all

現在您可以在您的 git 遙控器中添加您的新倉庫並將其推送到該倉庫

git remote remove origin <old-repo>
git remote add origin <new-repo>
git push origin <current-branch>

添加-f覆蓋

使用來自http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/的靈感,我創建了這個 Powershell 函數來做同樣的事情,它有到目前為止對我來說效果很好:

# Migrates the git history of a file or directory from one Git repo to another.
# Start in the root directory of the source repo.
# Also, before running this, I recommended that $destRepoDir be on a new branch that the history will be migrated to.
# Inspired by: http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/
function Migrate-GitHistory
{
    # The file or directory within the current Git repo to migrate.
    param([string] $fileOrDir)
    # Path to the destination repo
    param([string] $destRepoDir)
    # A temp directory to use for storing the patch file (optional)
    param([string] $tempDir = "\temp\migrateGit")

    mkdir $tempDir

    # git log $fileOrDir -- to list commits that will be migrated
    Write-Host "Generating patch files for the history of $fileOrDir ..." -ForegroundColor Cyan
    git format-patch -o $tempDir --root -- $fileOrDir

    cd $destRepoDir
    Write-Host "Applying patch files to restore the history of $fileOrDir ..." -ForegroundColor Cyan
    ls $tempDir -Filter *.patch  `
        | foreach { git am $_.FullName }
}

此示例的用法:

git clone project2
git clone project1
cd project1
# Create a new branch to migrate to
git checkout -b migrate-from-project2
cd ..\project2
Migrate-GitHistory "deeply\buried\java\source\directory\A" "..\project1"

完成此操作后,您可以在合並之前重新組織migrate-from-project2分支上的文件。

我想要一些健壯且可重用的東西(一個命令並執行 + 撤消功能),所以我編寫了以下 bash 腳本。 多次為我工作,所以我想我會在這里分享。

它能夠將任意文件夾/path/to/foorepo1/some/other/folder/barrepo2 (文件夾路徑可以相同或不同,與根文件夾的距離可能不同)。

由於它只檢查涉及輸入文件夾中文件的提交(而不是源存儲庫的所有提交),因此即使在大型源存儲庫中也應該非常快,如果您只是提取一個在每個文件中都沒有觸及的深層嵌套子文件夾犯罪。

因為這樣做是用所有舊倉庫的歷史創建一個孤立的分支,然后將它合並到 HEAD,它甚至可以在文件名沖突的情況下工作(然后你必須在最后解決合並) .

如果沒有文件名沖突,您只需要最后git commit即可完成合並。

缺點是它可能不會跟隨源 repo 中的文件重命名(在REWRITE_FROM文件夾之外) - 歡迎在 GitHub 上拉取請求以適應這一點。

GitHub 鏈接: git-move-folder-between-repos-keep-history

#!/bin/bash

# Copy a folder from one git repo to another git repo,
# preserving full history of the folder.

SRC_GIT_REPO='/d/git-experimental/your-old-webapp'
DST_GIT_REPO='/d/git-experimental/your-new-webapp'
SRC_BRANCH_NAME='master'
DST_BRANCH_NAME='import-stuff-from-old-webapp'
# Most likely you want the REWRITE_FROM and REWRITE_TO to have a trailing slash!
REWRITE_FROM='app/src/main/static/'
REWRITE_TO='app/src/main/static/'

verifyPreconditions() {
    #echo 'Checking if SRC_GIT_REPO is a git repo...' &&
      { test -d "${SRC_GIT_REPO}/.git" || { echo "Fatal: SRC_GIT_REPO is not a git repo"; exit; } } &&
    #echo 'Checking if DST_GIT_REPO is a git repo...' &&
      { test -d "${DST_GIT_REPO}/.git" || { echo "Fatal: DST_GIT_REPO is not a git repo"; exit; } } &&
    #echo 'Checking if REWRITE_FROM is not empty...' &&
      { test -n "${REWRITE_FROM}" || { echo "Fatal: REWRITE_FROM is empty"; exit; } } &&
    #echo 'Checking if REWRITE_TO is not empty...' &&
      { test -n "${REWRITE_TO}" || { echo "Fatal: REWRITE_TO is empty"; exit; } } &&
    #echo 'Checking if REWRITE_FROM folder exists in SRC_GIT_REPO' &&
      { test -d "${SRC_GIT_REPO}/${REWRITE_FROM}" || { echo "Fatal: REWRITE_FROM does not exist inside SRC_GIT_REPO"; exit; } } &&
    #echo 'Checking if SRC_GIT_REPO has a branch SRC_BRANCH_NAME' &&
      { cd "${SRC_GIT_REPO}"; git rev-parse --verify "${SRC_BRANCH_NAME}" || { echo "Fatal: SRC_BRANCH_NAME does not exist inside SRC_GIT_REPO"; exit; } } &&
    #echo 'Checking if DST_GIT_REPO has a branch DST_BRANCH_NAME' &&
      { cd "${DST_GIT_REPO}"; git rev-parse --verify "${DST_BRANCH_NAME}" || { echo "Fatal: DST_BRANCH_NAME does not exist inside DST_GIT_REPO"; exit; } } &&
    echo '[OK] All preconditions met'
}

# Import folder from one git repo to another git repo, including full history.
#
# Internally, it rewrites the history of the src repo (by creating
# a temporary orphaned branch; isolating all the files from REWRITE_FROM path
# to the root of the repo, commit by commit; and rewriting them again
# to the original path).
#
# Then it creates another temporary branch in the dest repo,
# fetches the commits from the rewritten src repo, and does a merge.
#
# Before any work is done, all the preconditions are verified: all folders
# and branches must exist (except REWRITE_TO folder in dest repo, which
# can exist, but does not have to).
#
# The code should work reasonably on repos with reasonable git history.
# I did not test pathological cases, like folder being created, deleted,
# created again etc. but probably it will work fine in that case too.
#
# In case you realize something went wrong, you should be able to reverse
# the changes by calling `undoImportFolderFromAnotherGitRepo` function.
# However, to be safe, please back up your repos just in case, before running
# the script. `git filter-branch` is a powerful but dangerous command.
importFolderFromAnotherGitRepo(){
    SED_COMMAND='s-\t\"*-\t'${REWRITE_TO}'-'

    verifyPreconditions &&
    cd "${SRC_GIT_REPO}" &&
      echo "Current working directory: ${SRC_GIT_REPO}" &&
      git checkout "${SRC_BRANCH_NAME}" &&
      echo 'Backing up current branch as FILTER_BRANCH_BACKUP' &&
      git branch -f FILTER_BRANCH_BACKUP &&
      SRC_BRANCH_NAME_EXPORTED="${SRC_BRANCH_NAME}-exported" &&
      echo "Creating temporary branch '${SRC_BRANCH_NAME_EXPORTED}'..." &&
      git checkout -b "${SRC_BRANCH_NAME_EXPORTED}" &&
      echo 'Rewriting history, step 1/2...' &&
      git filter-branch -f --prune-empty --subdirectory-filter ${REWRITE_FROM} &&
      echo 'Rewriting history, step 2/2...' &&
      git filter-branch -f --index-filter \
       "git ls-files -s | sed \"$SED_COMMAND\" |
        GIT_INDEX_FILE=\$GIT_INDEX_FILE.new git update-index --index-info &&
        mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" HEAD &&
    cd - &&
    cd "${DST_GIT_REPO}" &&
      echo "Current working directory: ${DST_GIT_REPO}" &&
      echo "Adding git remote pointing to SRC_GIT_REPO..." &&
      git remote add old-repo ${SRC_GIT_REPO} &&
      echo "Fetching from SRC_GIT_REPO..." &&
      git fetch old-repo "${SRC_BRANCH_NAME_EXPORTED}" &&
      echo "Checking out DST_BRANCH_NAME..." &&
      git checkout "${DST_BRANCH_NAME}" &&
      echo "Merging SRC_GIT_REPO/" &&
      git merge "old-repo/${SRC_BRANCH_NAME}-exported" --no-commit &&
    cd -
}

# If something didn't work as you'd expect, you can undo, tune the params, and try again
undoImportFolderFromAnotherGitRepo(){
  cd "${SRC_GIT_REPO}" &&
    SRC_BRANCH_NAME_EXPORTED="${SRC_BRANCH_NAME}-exported" &&
    git checkout "${SRC_BRANCH_NAME}" &&
    git branch -D "${SRC_BRANCH_NAME_EXPORTED}" &&
  cd - &&
  cd "${DST_GIT_REPO}" &&
    git remote rm old-repo &&
    git merge --abort
  cd -
}

importFolderFromAnotherGitRepo
#undoImportFolderFromAnotherGitRepo

git subtree可以直觀地工作,甚至可以保留歷史記錄。

示例用法:將 git repo 添加為子目錄:

git subtree add --prefix foo https://github.com/git/git.git master

解釋:

#├── repo_bar
#│   ├── bar.txt
#└── repo_foo
#    └── foo.txt

cd repo_bar
git subtree add --prefix foo ../repo_foo master

#├── repo_bar
#│   ├── bar.txt
#│   └── foo
#│       └── foo.txt
#└── repo_foo
#    └── foo.txt

就我而言,我不需要保留要從中遷移的存儲庫或保留任何以前的歷史記錄。 我有一個相同分支的補丁,來自不同的遙控器

#Source directory
git remote rm origin
#Target directory
git remote add branch-name-from-old-repo ../source_directory

在這兩個步驟中,我能夠讓另一個 repo 的分支出現在同一個 repo 中。

最后,我設置了這個分支(我從另一個倉庫導入的)跟隨目標倉庫的主線(這樣我就可以准確地區分它們)

git br --set-upstream-to=origin/mainline

現在它表現得好像它只是我針對同一個 repo 推送的另一個分支。

如果兩個存儲庫中相關文件的路徑相同,並且您只想帶入一個文件或一小組相關文件,那么一種簡單的方法是使用git cherry-pick

第一步是使用git fetch <remote-url>將來自其他 repo 的提交帶入您自己的本地 repo。 這將使FETCH_HEAD指向另一個倉庫的頭部提交; 如果您想在完成其他提取后保留對該提交的引用,您可能需要使用git tag other-head FETCH_HEAD對其進行標記。

然后,您將需要為該文件創建一個初始提交(如果它不存在)或一個提交以使該文件進入一個可以使用您想要引入的其他存儲庫的第一個提交進行修補的狀態。您可以如果commit-0引入了您想要的文件,則可以使用git cherry-pick <commit-0>執行此操作,或者您可能需要“手動”構建提交。 如果您需要修改初始提交,例如,從該提交中刪除您不想引入的文件,請將-n添加到cherry-pick 選項中。

之后,您可以繼續git cherry-pick后續提交,必要時再次使用-n 在最簡單的情況下(所有提交正是您想要的並干凈地應用),您可以在 cherry-pick 命令行上提供完整的提交列表: git cherry-pick <commit-1> <commit-2> <commit-3> ... .

我做了什么:

  1. 將存儲庫克隆到文件夾
  2. cd 現有項目
  3. 在這里打開一個 git 終端
  4. git remote set-url origin <NEW_GIT_URL>
  5. git push -u origin --all
  6. git push origin --tags

不需要 linux 或 Github 命令

1)在線訪問github。 2)使用您要移動的文件轉到舊存儲庫。 3)原始文件內容復制。 我的是 PytorchImageSegmentation.ipynb 4)創建新存儲庫並輸入它 5)單擊添加新文件,並創建新文件 6)將內容粘貼到文件中 7)賦予文件與其他存儲庫相同的擴展名。 我的 was.ipynb 和我保持相同的標題,所以在新的 repo 中它也是 PytorchImageSegmentation.ipynb。

文件已移動。 沒有嘗試過文件夾。 我不認為這是可能的。

以下通過維護所有分支並保留歷史記錄將我的 GIT Stash 遷移到 GitLab 的方法。

將舊存儲庫克隆到本地。

git clone --bare <STASH-URL>

在 GitLab 中創建一個空存儲庫。

git push --mirror <GitLab-URL>

當我們將代碼從 stash 遷移到 GitLab 時,我執行了上述操作,並且效果非常好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM