Git में केवल फ़ोल्डर संरचना के साथ संशोधित और जोड़े गए फ़ाइलों को निर्यात करें


83

मैं एक विशिष्ट प्रतिबद्ध में संशोधित और जोड़ी गई फ़ाइलों की एक सूची प्राप्त करना चाहूंगा ताकि मैं उन्हें निर्यात कर सकूं और फ़ाइल संरचना के साथ एक पैकेज तैयार कर सकूं।

पैकेज प्राप्त करने और सर्वर पर इसे निकालने का विचार है। कई कारणों से मैं रेपो को स्वचालित रूप से खींचने के लिए एक हुक नहीं बना सकता हूं और सर्वर को अपडेट रखने का सबसे आसान तरीका यह पैकेज उत्पन्न कर रहा है।

जवाबों:


107
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id
  1. git diff-tree -r $commit_id:

    अपने माता-पिता (सभी उपनिर्देशिकाओं सहित, न केवल शीर्ष निर्देशिका के लिए) को दिए गए वचनबद्धताओं का भिन्न रूप लें।

  2. --no-commit-id --name-only:

    प्रतिबद्ध SHA1 आउटपुट न करें। केवल एक पूर्ण अंतर के बजाय प्रभावित फ़ाइलों के नाम आउटपुट।

  3. --diff-filter=ACMRT:

    इस कमिट में केवल जोड़ी गई फाइलों को जोड़ा गया, कॉपी किया गया, संशोधित किया गया, नाम बदला गया या जिसमें उनका प्रकार बदल गया था (जैसे। फ़ाइल → सिमलिंक)। यह हटाई गई फ़ाइलों को छोड़ देता है।


टिप्पणी से अद्यतन:
नीचे दिए गए आदेश के साथ प्रश्न संदर्भ और टिप्पणियों के आधार पर, आप ACMRTफ़ाइलों को .tarउनके फ़ोल्डर संरचना के साथ एक फ़ाइल के रूप में प्राप्त कर सकते हैं ।

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -

अब मुझे बस ou को टार के साथ इस कमांड के परिणाम को गोंद करने का एक तरीका खोजना है! धन्यवाद!
माइकल कुहिनिका 21

8
@Taverneiro आप इस उत्तर में दिए गए टार कमांड को पाइप कर सकते हैं , जैसे। tgz फ़ाइल के लिए:git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
Matthieu Sadouni

68
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | xargs tar -rf mytarfile.tar

बस इसे राउंड करने के लिए, यहाँ कमांड टार करने के लिए पाइप किया गया है। यह फाइलों को टार आर्काइव में एक्सपोर्ट करता है।


1
क्या यह एक टार फाइल में कई कमिट के लिए किया जा सकता है?
evolutionxbox

4
जब एक ही टार फाइल में कई कॉम्पटिट जोड़ने की कोशिश की जाती है, तो कभी-कभी टार फाइलनेम बनाता है। फिर से अन्य नाम (फाइलनाम 1 .ext) के साथ। मुझे लगता है कि अगर मैं ज़िप का उपयोग करता हूं, तो मैं फ़ाइल को जोड़ सकता हूं और अगर वह ज़िप में मौजूद है तो उसे अधिलेखित कर सकता हूं ... आपको बस xargs को xargs zip -r0 myzipfile.zip से $ 1 में बदलने की आवश्यकता है
Martins

क्या यहाँ xargs की ज़रूरत है? मुझे पता है कि यह आरएम जैसे सामान के लिए है, लेकिन मुझे लगा कि टार आप जितनी चाहें उतनी फाइलें संभाल सकते हैं।
एरडाल जी।

1
इस जवाब के साथ सावधान, यह ले diff फ़ाइलें हो लेकिन मौजूदा शाखा के वर्तमान संस्करण के रूप में
एमईएमएस

1
विंडोज़ स्लेव मशीन में इस कमांड को निष्पादित करते समय, मुझे निम्न त्रुटि मिल रही है "आंतरिक या बाहरी कमांड, ऑपरेशनल प्रोग्राम या बैच फ़ाइल के रूप में 'xargs' को मान्यता नहीं मिली है।"
नवीन प्रसाद

40

यहां एक पंक्ति की एक कमांड है जो विंडोज 7 पर काम करती है। इसे अपने रिपॉजिटरी के शीर्ष-स्तरीय फ़ोल्डर से चलाएं।

for / f "यूज़बैकq टोकन = *"% A इन (`गिट डिफरेंट-ट्री -r -no-प्रतिबद्ध-आईडी - केवल -diff-filter = ACMRT HEAD ~ 1 HEAD`) करते हैं प्रतिध्वनि एफए | xcopy | "% ~ fA" "C: \ git_changed_files \% A"

  • इको एफए एक फ़ाइल या निर्देशिका (फ़ाइल) की प्रतिलिपि बना रहा है, और एक फ़ाइल को अधिलेखित करने के बारे में संभावित प्रश्न (सभी को अधिलेखित करें) के बारे में अपरिहार्य xcopy प्रश्न का उत्तर देता है।
  • यूज़बैक हमारे आउटपुट से इनपुट के रूप में हमारे git कमांड से आउटपुट का उपयोग करने की अनुमति देता है
  • HEAD ~ 1 HEAD में पिछली प्रतिबद्धताओं और वर्तमान HEAD के बीच सभी अंतर हैं
  • % ~ fA git आउटपुट को पूरी तरह से योग्य पथ में बदल देता है (बैकस्लैश के लिए आगे स्लैश बदलने की आवश्यकता होती है)
  • C: \ git_changed_files \ वह जगह है जहाँ आपको सभी फाइलें अलग-अलग मिलेंगी

1
जब मैंने प्रतीकों की उस गड़बड़ी को देखा तो मुझे यह उम्मीद नहीं थी कि मैं इसे व्यापक ट्विकिंग के बिना काम कर सकता हूं ... लेकिन इसने पहले प्रयास पर काम किया, धन्यवाद।
नाथन अंजीर

3
उन सभी लोगों के लिए एक छोटा सा सिर जो (मेरे जैसे) विंडो बैच फ़ाइलों से बहुत परिचित नहीं हैं: यदि आप एक बैच फ़ाइल में उपरोक्त कमांड का उपयोग करना चाहते हैं, तो आपको लूप के लिए% A के साथ% A को बदलना होगा।
बुडबुल

1
क्या? जबरदस्त हंसी। बस git आर्काइव का उपयोग करें - git diff कॉम्बो (निकोलस का उत्तर)। बहुत आसान और सीधा। (मैं ईमानदारी से नहीं जानता कि यहाँ क्या हो रहा है।)
ADTC

1
चेतावनी: यह आपकी वर्किंग कॉपी से फाइलों को कॉपी करेगा, जो वास्तव में HEAD में मेल नहीं खा सकता है (या जो भी हैश आपके साथ इसे बदलें)
साइमन ईस्ट

1
महान सामान, लेकिन केवल सीएमडी के साथ काम करता है Powershell; -v ° v-
रोडियन बाईकोव

33

यदि आपका कमिट हैश उदाहरण के लिए a9359f9 है, तो यह कमांड:

git archive -o patch.zip a9359f9 $(git diff --name-only a9359f9^..a9359f9)

प्रतिबद्ध में संशोधित फ़ाइलों को निकालने और उन्हें परियोजना निर्देशिका संरचना बरकरार रखते हुए पैच.ज़िप में रखें।

एक बिट क्रिया, प्रतिबद्ध हैश का तीन बार उल्लेख किया गया है, लेकिन यह मेरे लिए काम करता है।

यहाँ मिल गया: http://tosbourn.com/2011/05/git/use-git-to-create-an-archive-of-changed-files/


मुझे लगता है मैं उपयोग कर सकते हैं functionमें PowerShell सिर्फ एक समारोह नाम के आदेश को कम करने और उपयोग करने के लिए $argsपारित करने के लिए हैश सिर्फ एक बार के लिए प्रतिबद्ध है। * निक्स में, आप समान प्रभाव को प्राप्त करने के लिए शेल-स्क्रिप्टिंग का उपयोग कर सकते हैं।
ADTC

1
यार ... मैं तुम्हें एक बीयर :)
deanpodgornik

3
@BenSewards कमिट 1 और कमिट 2 के बीच कमिट्स की सीमा के लिए (बाद के कमिट को मिलाकर, पहले वाली कमिटमेंट के लिए विशेष; ऑर्डर कोई फर्क नहीं पड़ता) बस करते हैं git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1 commit2)archiveकमांड को दी गई कमिटमेंट किसी भी मनमाने तरीके से की जा सकती है (सबसे अधिक संभावना या तो HEAD या बाद की कमिट) , और फाइलों को ऐसे खींचा जाता है मानो उस कमिट स्टेज पर उनकी जाँच हो। Commit1 और commit2 के लिए पारित diffकेवल पुल करने के लिए फ़ाइलों की सूची उत्पन्न करने के लिए उपयोग किया जाता है - वे खींच लिया फ़ाइलों के संस्करण को प्रभावित नहीं करते।
ADTC

1
अतिरिक्त टिप: यदि आप एक संग्रह में कई श्रेणियों की परिवर्तित फ़ाइलों को एक संग्रह में जोड़ना चाहते हैं, तो केवल diffअर्धविराम के साथ कमांड दोहराएं :git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1A commit1B; git diff --name-only commit2A commit2B; git diff --name-only commit3A commit3B)
ADTC

4
पथ नामों में रिक्त स्थान के कारण मुझे NUL को संभालने वाले xargs के लिए एक पाइप का उपयोग करना पड़ाgit diff -z --name-only commit1 commit2 | xargs -0 git archive -o patch.zip HEAD
बोगिन

27

आप MS Windows में Tortoise Git का उपयोग कर निर्यात कर सकते हैं :

मैं राइट क्लिक करें और TortoiseGit का चयन करें > लॉग दिखाएँ और लॉग संदेश खुले होंगे।

दो संशोधनों का चयन करें और इसकी तुलना करें। के बीच अंतर खुला रहेगा।

एक फ़ोल्डर में फ़ाइलों और निर्यात चयन का चयन करें ... !

यहां छवि विवरण दर्ज करें


1
निश्चित रूप से। इतने सारे जवाबों में लाइनक्स-ओनली कमांड्स थे, और बहुतों ने काम के बदलावों पर कब्जा नहीं किया था, केवल वही बदलाव हुए जो प्रतिबद्ध थे। खुशी है कि यह पोस्ट किया गया था!
डाईथिम

8

मुझे अपने परीक्षण सर्वर को अपडेट करने और संस्करण 2.1 के बाद से परिवर्तित फ़ाइलों को जोड़ने की आवश्यकता थी।
मेरे लिए जेम्स एहली के पोस्ट के समान समाधान काम किया, लेकिन मेरे मामले में मैं दो पुराने टैग - tag_ver_2.1 और tag_ver_2.2 के बीच अंतर के संग्रह पैकेज को निर्यात करना चाहता था केवल एक ही प्रतिबद्ध नहीं था।

उदाहरण के लिए:

tag_ver_2.1 = 1f72b38ad
tag_ver_2.2 = c1a546782

यहाँ संशोधित उदाहरण है:

git diff-tree -r --no-commit-id --name-only c1a546782 1f72b38ad | xargs tar -rf test.tar

मैंने अभी एक WEIRD समस्या का पता लगाया है: यदि मैं ऊपर दिए गए कोड को आज़माता हूँ तो यह एक आकर्षण की तरह काम करता है। लेकिन मैं tar -rf test.tar को tar -zcf test.tar.gz के लिए बदल देता हूं, फिर परिणामी फाइल में कई फाइलें गायब हैं। परिणाम में इस अंतर का क्या कारण हो सकता है?
अल्बर्टो अलेक्जेंडर रोड्रिगेज

विंडोज़ स्लेव मशीन में इस कमांड को निष्पादित करते समय, मुझे निम्न त्रुटि मिल रही है "आंतरिक या बाहरी कमांड, ऑपरेशनल प्रोग्राम या बैच फ़ाइल के रूप में 'xargs' को मान्यता नहीं मिली है।"
नवीन प्रसाद

4

नीचे आज्ञाओं ने मेरे लिए काम किया।

यदि आप अंतिम कमिट द्वारा परिवर्तित की गई फ़ाइलों का अंतर चाहते हैं:

git archive -o update.zip HEAD $(git diff --name-only HEAD HEAD^)

या यदि आप दो विशिष्ट आवागमन के बीच अंतर चाहते हैं:

git archive -o update.zip sha1 $(git diff --name-only sha1 sha2)

या यदि आपके पास फाइलें नहीं हैं, तो याद रखें कि git तरीका सब कुछ करने के लिए है, शाखाएं सस्ती हैं:

git stash
git checkout -b feature/new-feature
git stash apply
git add --all
git commit -m 'commit message here'
git archive -o update.zip HEAD $(git diff --name-only HEAD HEAD^)

2

मैंने विंडोज़ पर परिवर्तित फ़ाइलों को निर्यात करने के लिए एक php स्क्रिप्ट बनाई है। यदि आपके पास php सेट अप के साथ एक लोकलहोस्ट डेवलपमेंट सर्वर है तो आप इसे आसानी से चला सकते हैं। यह आपके पिछले रिपॉजिटरी को याद रखेगा और हमेशा एक ही फ़ोल्डर में निर्यात करेगा। निर्यात करने से पहले निर्यात फ़ोल्डर को हमेशा खाली किया जाता है। आपको लाल रंग में हटाई गई फ़ाइलें भी दिखाई देंगी, ताकि आप जान सकें कि सर्वर पर क्या हटाना है।

ये सिर्फ दो फाइलें हैं इसलिए मैं उन्हें यहां पोस्ट करूंगा। मान लेते हैं कि आपके रिपॉजिटरी अपने स्वयं के फ़ोल्डरों में c: / www के तहत स्थित हैं और http: // localhost भी c: / www को इंगित करता है और php-enable है। आइए इन 2 फाइलों को c: / www / git-export में डालें -

index.php:

<?php
/* create directory if doesn't exist */
function createDir($dirName, $perm = 0777) {
    $dirs = explode('/', $dirName);
    $dir='';
    foreach ($dirs as $part) {
        $dir.=$part.'/';
        if (!is_dir($dir) && strlen($dir)>0) {
            mkdir($dir, $perm);
        }
    }
}

/* deletes dir recursevely, be careful! */
function deleteDirRecursive($f) {

    if (strpos($f, "c:/www/export" . "/") !== 0) {
        exit("deleteDirRecursive() protection disabled deleting of tree: $f  - please edit the path check in source php file!");
    }

    if (is_dir($f)) {
        foreach(scandir($f) as $item) {
            if ($item == '.' || $item == '..') {
                continue;
            }

            deleteDirRecursive($f . "/" . $item);
        }    
        rmdir($f);

    } elseif (is_file($f)) {
        unlink($f);
    }
}

$lastRepoDirFile = "last_repo_dir.txt";
$repo = isset($_POST['repo']) ? $_POST['repo'] : null;


if (!$repo && is_file($lastRepoDirFile)) {
    $repo = file_get_contents($lastRepoDirFile);
}

$range = isset($_POST['range']) ? $_POST['range'] : "HEAD~1 HEAD";


$ini = parse_ini_file("git-export.ini");

$exportDir = $ini['export_dir'];
?>

<html>
<head>
<title>Git export changed files</title>
</head>

<body>
<form action="." method="post">
    repository: <?=$ini['base_repo_dir'] ?>/<input type="text" name="repo" value="<?=htmlspecialchars($repo) ?>" size="25"><br/><br/>

    range: <input type="text" name="range" value="<?=htmlspecialchars($range) ?>" size="100"><br/><br/>

    target: <strong><?=$exportDir ?></strong><br/><br/>

    <input type="submit" value="EXPORT!">
</form>

<br/>


<?php
if (!empty($_POST)) {

    /* ************************************************************** */
    file_put_contents($lastRepoDirFile, $repo); 

    $repoDir = $ini['base_repo_dir'] ."/$repo";
    $repoDir = rtrim($repoDir, '/\\');

    echo "<hr/>source repository: <strong>$repoDir</strong><br/>";
    echo "exporting to: <strong>$exportDir</strong><br/><br/>\n";


    createDir($exportDir);

    // empty export dir
    foreach (scandir($exportDir) as $file) {
        if ($file != '..' && $file != '.') {
            deleteDirRecursive("$exportDir/$file");
        }
    }

    // execute git diff
    $cmd = "git --git-dir=$repoDir/.git diff $range --name-only";

    exec("$cmd 2>&1", $output, $err);

    if ($err) {
        echo "Command error: <br/>";
        echo implode("<br/>", array_map('htmlspecialchars', $output));
        exit;
    }


    // $output contains a list of filenames with paths of changed files
    foreach ($output as $file) {

        $source = "$repoDir/$file";

        if (is_file($source)) {
            if (strpos($file, '/')) {
                createDir("$exportDir/" .dirname($file));
            }

            copy($source, "$exportDir/$file");
            echo "$file<br/>\n";

        } else {
            // deleted file
            echo "<span style='color: red'>$file</span><br/>\n";
        }
    }
}
?>

</body>
</html>

git-export.ini:

; path to all your git repositories for convenience - less typing
base_repo_dir = c:/www

; if you change it you have to also change it in the php script
; in deleteDirRecursive() function - this is for security
export_dir = c:/www/export

और अब एक ब्राउज़र में लोकलहोस्ट / गिट-एक्सपोर्ट / लोड करें। स्क्रिप्ट को हमेशा c: / www / निर्यात में निर्यात करने के लिए सेट किया गया है - अपने वातावरण के अनुरूप होने के लिए सभी मार्ग बदलें या अपनी आवश्यकताओं के अनुरूप स्क्रिप्ट को संशोधित करें।

यदि आप Git स्थापित कर चुके हैं तो यह काम करेगा ताकि git कमांड आपके PATH में हो - जब आप विंडोज़ Git इंस्टॉलर चलाते हैं तो इसे कॉन्फ़िगर किया जा सकता है।


यह कोड बहुत अच्छा है, लेकिन मुझे सबमॉड्यूल्स वाली एक्सपोर्ट फाइल्स और डिरेक्ट्रीज़ चाहिए, आपके कोड ने केवल मुख्य रिपॉजिटरी के साथ काम किया और अगर सबमॉड्यूल्स ने आपका कोड बदल दिया तो सबमॉड्यूल फोल्डर डिलीट कर दें!
मोर्टिजा खादिम

1

दिनांक के साथ संशोधित फ़ाइलों को निर्यात करने के लिए:

  diff --stat @{2016-11-01} --diff-filter=ACRMRT --name-only | xargs tar -cf 11.tar

शॉर्टकट (उपनाम का उपयोग करें)

  git exportmdf 2016-11-01 11.tar

एलियास इन .gitconfig

  [alias]
  exportmdf = "!f() { \
    git diff --stat @{$1} --diff-filter=ACRMRT --name-only | xargs tar -cf $2; \
  }; f"

0

यहाँ एक छोटा सा बैश (यूनिक्स) स्क्रिप्ट है जो मैंने लिखा है कि फ़ोल्डर संरचना के साथ दिए गए कमिट हैश के लिए फाइल कॉपी करेगा:

ARRAY=($(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $1))
PWD=$(pwd)

if [ -d "$2" ]; then

    for i in "${ARRAY[@]}"
    do
        : 
        cp --parents "$PWD/$i" $2
    done
else
    echo "Chosen destination folder does not exist."
fi

'~ / Scripts / copy-commit.sh' नाम की एक फ़ाइल बनाएँ, फिर उसे निष्पादन विशेषाधिकार दें:

chmod a+x ~/Scripts/copy-commit.sh

फिर, गैट भंडार की जड़ से:

~/Scripts/copy-commit.sh COMMIT_KEY ~/Existing/Destination/Folder/

0

मैंने भी पहले इसी तरह की समस्या का सामना किया था। मैंने एक सरल शेल स्क्रिप्ट लिखी।

$git log --reverse commit_HashX^..commit_HashY --pretty=format:'%h'

उपरोक्त आदेश, कमिटमेंट में हैश (रिविजन) को__ashX से कम_हैशी को रिवर्स ऑर्डर में प्रदर्शित करेगा।

 456d517 (second_hash)
 9362d03
 5362d03
 226x47a
 478bf6b (six_hash)

अब ऊपर के कमांड का उपयोग करते हुए मुख्य शेल स्क्रिप्ट।

commitHashList=$(git log --reverse $1^..$2 --pretty=format:'%h')
for hash in $commitHashList
do
    echo "$hash"
    git archive -o \Path_Where_you_want_store\ChangesMade.zip $hash
done

इस कोड को export_changes.sh में जोड़ें। अब फाइल को पास करें और स्क्रिप्ट को हैश करें।

सुनिश्चित करें कि आरंभिक कमिट_हश का पहला तर्क होना चाहिए और फिर अंतिम कम से कम उस तक होना चाहिए, जिसमें आप परिवर्तन निर्यात करना चाहते हैं।

उदाहरण:

$ श Export_changes.sh हैश एक्स हैश

इस स्क्रिप्ट को git स्थानीय निर्देशिका में डालें या स्क्रिप्ट में git स्थानीय निर्देशिका पथ सेट करें। आशा है कि इससे सहायता मिलेगी..!


0

यह मेरे लिए यूनिक्स और विंडोज दोनों के लिए काम करता है:

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT __1__.. | xargs cp --parents -t __2__

कमांड में दो प्लेसहोल्डर हैं। आपको उन्हें अपने उद्देश्य के लिए प्रतिस्थापित करने की आवश्यकता है:

  • __1__ : उन सभी कमिट्स के सही होने से पहले कमिट आईडी के साथ बदलें , जिन्हें आप निर्यात करना चाहते हैं (जैसे 997cc7b6 - कमिट आईडी के बाद उस डबलडॉट को रखना न भूलें - इसका अर्थ है "इस कमिट की तुलना में सभी नए शामिल करें")

  • __2__ : मौजूदा पथ से प्रतिस्थापित करें जहाँ आप अपनी फ़ाइलें निर्यात करना चाहते हैं (जैसे ../export_path/)

परिणामस्वरूप आप एक फ़ोल्डर संरचना (कोई ज़िप / tars ...) में अपनी फ़ाइलों को प्राप्त करेंगे क्योंकि किसी को svn रिपॉजिटरी में कछुआ svn निर्यात का उपयोग करने के लिए इस्तेमाल किया जा सकता है।

यह उदाहरण के लिए बहुत उपयोगी है जब आप कुछ अंतिम कमिट की गयी / संशोधित फ़ाइलों की मैन्युअल तैनाती करना चाहते हैं। तो आप इन फ़ाइलों को ftp क्लाइंट के माध्यम से कॉपी कर सकते हैं।


0

मेरी भी यही समस्या थी। @NicolasDermine का समाधान काम नहीं किया क्योंकि तुलनात्मक कमिट के बीच बहुत सारी फाइलें बदल गई हैं। मुझे एक त्रुटि मिली कि शेल तर्क बहुत लंबे हैं।

एक परिणाम के रूप में मैंने अजगर के कार्यान्वयन को जोड़ा। इस के माध्यम से स्थापित किया जा सकता है pip install gitzipऔर फिर से निष्पादित किया जा सकता है

python -m gitzip export.zip <commit id> <commit id>

रिपॉजिटरी रूट export.zipमें डायरेक्टरी स्ट्रक्चर को बरकरार रखते हुए सभी बदली हुई फाइलों वाली फाइल बनाते हुए।

हो सकता है कि किसी को इसकी आवश्यकता हो इसलिए मैंने इसे यहां साझा करने के लिए सोचा।

अस्वीकरण : मैं gitzip मॉड्यूल का लेखक हूं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.