Jak przenieść pliki z jednego repo git do drugiego (nie klona), zachowując historię

Nasze repozytoria Git zaczynały jako część pojedynczego repozytorium monster SVN, gdzie poszczególne projekty miały swoje własne drzewo w ten sposób:

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

Oczywiście bardzo łatwo było przenosić pliki z jednego do drugiego za pomocą svn mv. Ale w Git, każdy projekt jest w swoim repozytorium, i dzisiaj zostałem poproszony o przeniesienie podkatalogu z project2 do project1. Zrobiłem coś takiego:

$ 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 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
Ale to wydaje się dość zawiłe. Czy jest lepszy sposób na takie rzeczy w ogóle? A może przyjęłam właściwe podejście?

Zauważ, że polega to na połączeniu historii z istniejącym repozytorium, a nie na tworzeniu nowego samodzielnego repozytorium z części innego repozytorium ( jak w poprzednim pytaniu ).

Author: ebneter, 2009-09-02

12 answers

Tak, uderzanie w --subdirectory-filter z filter-branch było kluczem. Fakt, że użyłeś go zasadniczo dowodzi, że nie ma łatwiejszego sposobu - nie miałeś wyboru, jak tylko przepisać historię, ponieważ chciałeś skończyć tylko z (przemianowanym) podzbiorem plików, a to z definicji zmienia hasze. Ponieważ żadne ze standardowych poleceń (np. pull) nie przepisuje historii, nie ma możliwości użycia ich w tym celu.

Oczywiście mógłbyś dopracować szczegóły - część twojego klonowania i rozgałęziania nie była ściśle konieczne - ale ogólne podejście jest dobre! Szkoda, że to skomplikowane, ale oczywiście, celem Gita nie jest ułatwianie przepisywania historii.
 46
Author: Cascabel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 08:11:27

Jeśli Twoja historia jest zdrowa, możesz usunąć commity jako łatkę i zastosować je w nowym repozytorium:

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

Lub w jednym wierszu

git log --pretty=email --patch-with-stat --reverse -- path/to/file_or_folder | (cd /path/to/new_repository && git am)

(zaczerpnięte z exherbo ' s docs )

 223
Author: Smar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-06 08:28:14

Po wypróbowaniu różnych metod przenoszenia pliku lub folderu z jednego repozytorium Git do drugiego, jedyne, które wydaje się działać niezawodnie, zostało opisane poniżej.

Polega na klonowaniu repozytorium, z którego chcesz przenieść plik lub folder, przenoszeniu tego pliku lub folderu do katalogu głównego, przepisywaniu historii Gita, klonowaniu repozytorium docelowego i ciągnięciu pliku lub folderu z historią bezpośrednio do tego repozytorium docelowego.

Etap Pierwszy

  1. Zrób kopię repozytorium A, ponieważ następujące kroki sprawiają, że główne zmiany w tej kopii, których nie należy naciskać!

    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
    
    Jeśli chcesz skopiować repozytorium myprojects]}
  2. Cd into it

    cd <git repository A directory>          eg. cd /c/Working/GIT/myprojects
    
  3. Usuń link do oryginalnego repozytorium, aby uniknąć przypadkowego dokonywanie wszelkich zdalnych zmian (np. przez pchnięcie)

    git remote rm origin
    
  4. Przejrzyj swoją historię i pliki, usuwając wszystko, co nie jest w katalog 1. Rezultatem jest zawartość of directory 1 do bazy repozytorium A.

    git filter-branch --subdirectory-filter <directory> -- --all
    eg. git filter-branch --subdirectory-filter subfolder1/subfolder2/FOLDER_TO_KEEP -- --all
    
  5. Tylko dla pojedynczego pliku przenieś: przejrzyj to, co zostało i usuń wszystko oprócz żądanego pliku. (Może być konieczne usunięcie plików nie chcesz o tym samym imieniu i zobowiązać się.)

    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, aby zachować tylko pom.plik xml z FOLDER_TO_KEEP

Etap Drugi

  1. Czyszczenie krok

    git reset --hard
    
  2. Czyszczenie krok

    git gc --aggressive
    
  3. Czyszczenie krok

    git prune
    

Możesz zaimportować te pliki do repozytorium B w katalogu, który nie jest głównym:

  1. Stwórz ten katalog

    mkdir <base directory>             eg. mkdir FOLDER_TO_KEEP
    
  2. Przenieś pliki do tego katalogu

    git mv * <base directory>          eg. git mv * FOLDER_TO_KEEP
    
  3. Dodaj pliki do tego katalogu

    git add .
    
  4. Zatwierdź swoje zmiany i jesteśmy gotowi połączyć te pliki w nowe repozytorium

    git commit
    

Etap Trzy

  1. Zrób kopię repozytorium B, jeśli jeszcze go nie masz

    git clone <git repository B url>
    eg. git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git
    
    Jeśli chcesz skopiować repozytorium do folderu FOLDER_TO_KEEP, możesz je skopiować do folderu FOLDER_TO_KEEP.]}
  2. Cd into it

    cd <git repository B directory>          eg. cd /c/Working/GIT/FOLDER_TO_KEEP
    
  3. Utwórz zdalne połączenie z repozytorium A jako gałąź w repozytorium B

    git remote add repo-A-branch <git repository A directory>
    

    (repo-a-branch może być czymkolwiek - to tylko dowolna nazwa)

    eg. git remote add repo-A-branch /c/Working/GIT/myprojects
    
  4. Wyciągnij z tej gałęzi (zawierającej tylko katalog, który chcesz move) do repozytorium B.

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

    Pull kopiuje zarówno pliki, jak i historię. Uwaga: można użyć scalania zamiast pull, ale pull działa lepiej.

  5. Wreszcie, prawdopodobnie chcesz trochę posprzątać, usuwając pilota połączenie z repozytorium a

    git remote rm repo-A-branch
    
  6. Przyj i gotowe.
    git push
    
 54
Author: mcarans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 14:30:39

Znalazłem to bardzo przydatne. Jest to bardzo proste podejście, w którym tworzysz łatki, które są stosowane do nowego repo. Więcej szczegółów na tej stronie.

Zawiera tylko trzy kroki (skopiowane z bloga):

# 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

Jedynym problemem, który miałem, było to, że nie mogłem nałożyć wszystkich łatek na raz za pomocą

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

Pod Windows mam błąd InvalidArgument. Musiałem więc nakładać wszystkie plastry jeden po drugim.

 14
Author: anhoppe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-29 01:41:11

ZACHOWANIE NAZWY KATALOGU

Podkatalog-filter (lub krótsze polecenie Git subtree) działa dobrze, ale nie działa dla mnie, ponieważ usuwają nazwę katalogu z informacji o zatwierdzeniu. W moim scenariuszu chcę tylko scalić części jednego repozytorium do drugiego i zachować historię z pełną nazwą ścieżki.

Moim rozwiązaniem było użycie filtra drzewa i po prostu usunięcie niechcianych plików i katalogów z tymczasowego klonu repozytorium źródłowego, a następnie wyciągnięcie z tego klonu do mojego repozytorium docelowego w 5 prostych krokach.

# 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
 6
Author: Joachim Nilsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 14:06:07

Ta odpowiedź dostarcza ciekawych poleceń opartych na git am i przedstawione na przykładach, krok po kroku.

Cel

  • chcesz przenieść niektóre lub wszystkie pliki z jednego repozytorium do drugiego.
  • Chcesz zachować ich historię.
  • ale nie dbasz o utrzymanie tagów i gałęzi.
  • akceptujesz ograniczoną historię dla zmienionych plików (i plików w zmienionych katalogach).

Procedura

  1. Wyodrębnij historię w formacie e-mail przy użyciu
    git log --pretty=email -p --reverse --full-index --binary
  2. reorganizacja drzewa plików i zmiana nazwy pliku w historii [opcjonalne]
  3. zastosuj nową historię za pomocą git am

1. Wyodrębnij historię w formacie e-mail

Przykład: Wyodrębnij historię file3, file4 i file5

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

Wyczyść tymczasowy katalog miejsce docelowe

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

Oczyść swoje repo źródło

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

Wyodrębnij historię KAŻDEGO pliku w wiadomości e-mail format

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"' {} ';'

Niestety opcja --follow lub --find-copies-harder nie może być łączona z --reverse. Dlatego historia jest wycinana po zmianie nazwy pliku (lub po zmianie nazwy katalogu nadrzędnego).

Po: tymczasowa historia w formacie e-mail

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

2. Reorganizacja drzewa plików i zmiana nazwy pliku w historii [opcjonalne]

Załóżmy, że chcesz przenieść te trzy pliki do innego repo (może to być ten sam 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

Dlatego zreorganizuj swoje pliki:

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

Twoja tymczasowa historia jest teraz:

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

Zmień również nazwy plików w historii:

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

Notatka: to przepisuje historię, aby odzwierciedlić zmianę ścieżki i nazwy pliku.
      [[91]} (tj. zmiana nowej lokalizacji / nazwy w ramach nowego repo)


3. Zastosuj nową historię

Twój drugi repo to:

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

Zastosuj commity z tymczasowych plików historii:

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

Twój drugi repo jest teraz:

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

Użyj git status, aby zobaczyć ilość commitów gotowych do wypchnięcia: -)

Notatka: ponieważ historia została przepisana w celu odzwierciedlenia zmiany ścieżki i nazwy pliku:
      (tj. w porównaniu z lokalizacją / nazwą w poprzednim repo)

  • nie ma potrzeby git mv aby zmienić lokalizację / nazwę pliku.
  • Nie trzeba git log --follow aby uzyskać dostęp do pełnej historii.

Extra trick: Detect przemianowane / przeniesione pliki w Twoim repo

Aby wyświetlić listę plików, które zostały przemianowane:

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

Więcej dostosowań: możesz wykonać polecenie {[26] } używając opcji --find-copies-harder lub --reverse. Możesz również usunąć dwie pierwsze kolumny używając {[29] } i grepping complete pattern' {.* => .*}'.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
 4
Author: olibre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-08 22:18:51

Mając podobny swędzenie do Scratcha (tylko dla niektórych plików danego repozytorium) skrypt okazał się bardzo pomocny: git-import

Skrócona wersja polega na tym, że tworzy pliki łatek danego pliku lub katalogu ($object) z istniejącego repozytorium:

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

Które następnie zostaną zastosowane do nowego repozytorium:

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

Po szczegóły zajrzyj do góry:

 2
Author: ViToni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-21 23:30:09

Ten, którego zawsze używam jest tutaj http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/. Proste i szybkie.

Aby zapewnić zgodność ze standardami stackoverflow, oto procedura:

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
 2
Author: Hugh Perkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-04 18:23:49

Wykorzystanie inspiracji z http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/{[5]w tym samym celu stworzyłem tę funkcję Powershell, która do tej pory świetnie mi się sprawdziła:

# 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 }
}

Użycie dla tego przykładu:

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"

Po wykonaniu tej czynności, możesz ponownie uporządkować pliki w gałęzi migrate-from-project2 przed jej scaleniem.

 1
Author: crimbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 06:05:49

Chciałem czegoś solidnego i wielokrotnego użytku (funkcja one-command-and-go + undo), więc napisałem następujący skrypt bash. Pracował dla mnie przy kilku okazjach, więc pomyślałem, że podzielę się tym tutaj.

Jest w stanie przenieść dowolny folder /path/to/foo z repo1 do /some/other/folder/bar do repo2 (ścieżki folderów mogą być takie same lub różne, odległość od folderu głównego może być różna).

Ponieważ przechodzi tylko nad zatwierdzeniami, które dotykają plików w folderze wejściowym (nie nad wszystkimi zatwierdzeniami repo źródłowego), powinno to być dość szybkie nawet przy dużych repozytoriach źródłowych, jeśli po prostu wyodrębnisz głęboko zagnieżdżony podfolder, który nie był dotykany w każdym commicie.

Ponieważ to robi, to tworzy osieroconą gałąź z całą historią starego repo, a następnie Scala ją z głową, będzie działać nawet w przypadku starć nazw plików(wtedy będziesz musiał rozwiązać merge na końcu oczywiście).

Jeśli nie ma kolizji nazw plików, wystarczy git commit na końcu, aby zakończyć scalanie.

Minusem jest to, że prawdopodobnie nie będzie podążać za zmianą nazw plików (poza folderem REWRITE_FROM) W źródłowych żądaniach repo-pull powitanych na Githubie, aby je dostosować.

GitHub link: 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
 1
Author: jakub.g,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-02 21:30:17

W moim przypadku, nie musiałem zachować repo, z którego migrowałem, ani zachować żadnej poprzedniej historii. Miałem łatkę tej samej gałęzi, z innego pilota

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

W tych dwóch krokach udało mi się sprawić, by gałąź drugiego repo pojawiła się w tym samym repo.

Na koniec ustawiłem tę gałąź (którą zaimportowałem z innego repo) tak, aby podążała za linią główną docelowego repo (aby móc je dokładnie odróżnić)

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

Teraz zachowywał się jak-gdyby to była tylko kolejna gałąź, którą miałem / align = "left" /

 0
Author: Jason D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-22 23:26:55

Jeśli ścieżki dla danych plików są takie same w dwóch repozytoriach i chcesz przenieść tylko jeden plik lub mały zestaw powiązanych plików, jednym z łatwych sposobów na to jest użycie git cherry-pick.

Pierwszym krokiem jest przeniesienie commitów z innego repo do własnego lokalnego repo za pomocą git fetch <remote-url>. Spowoduje to, że FETCH_HEAD będzie wskazywał na główny commit z innego repo; jeśli chcesz zachować odniesienie do tego commita po wykonaniu innych pobrań, możesz go oznaczyć git tag other-head FETCH_HEAD.

Będziesz musiał utworzyć początkowy commit dla tego pliku (jeśli nie istnieje) lub commit, aby doprowadzić plik do stanu, który może być poprawiony z pierwszym commitem z innego repo, które chcesz wprowadzić. Możesz to zrobić za pomocą git cherry-pick <commit-0> Jeśli commit-0 wprowadziłeś pliki, które chcesz, lub możesz potrzebować stworzyć commit 'ręcznie'. Dodaj -n do opcji cherry-pick, jeśli chcesz zmodyfikować początkowy commit, np. upuść pliki z tego commita, którego nie chcesz wnieść do środka.

Następnie możesz kontynuować git cherry-pick kolejne commity, ponownie używając -n w razie potrzeby. W najprostszym przypadku (wszystkie commity są dokładnie takie, jakie chcesz zastosować) możesz podać pełną listę commitów w wierszu poleceń cherry-pick: git cherry-pick <commit-1> <commit-2> <commit-3> ....

 0
Author: Curt J. Sampson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 02:51:48